diff --git a/.agent/rules/breadboard.md b/.agent/rules/breadboard.md new file mode 100644 index 00000000000..d9259002520 --- /dev/null +++ b/.agent/rules/breadboard.md @@ -0,0 +1,79 @@ +--- +trigger: always_on +--- + +## Build system + +This is a monorepo that uses wireit as a build system. This means that the +commands in `package.json` files are typically wireit commands that invoke the +full build system to first ensure that all dependencies are satisfied. For +example: + +- `npm run build` or `npm run build:tsc` builds all monorepo dependencies and + then runs tsc to compile the target. +- `npm run test` first invokes build (or `build:tsc`) for all dependencies, then + runs testing. + +## Packages + +These are some significant packages: + +- `packages/types` -- contains only type definitons. This is package is designed + to allow defining types that are used across the package to avoid circular + references. Any time you need to add a cross-package type, add it here. + +- `packages/utils` -- contains commonly used functions and classes. If you're + looking to implement a helper function, first look in `packages/utils` to see + if it might be already present there. + +- `packages/breadboard`, `packages/runtime`, `packages/data`, `packages/loader` + -- contain the core runtime engine for the project and all the data + transformation/processing code. + +- `packages/visual-editor` -- contains the majority of the frontend code for the project. + +- `unified-server` -- contains the nodejs server, the backend of the project. + +## Signals + +The repo is using `signal-polyfil` and `signal-utils` as its signal infrastructure. + +## Coding Conventions + +### Exports + +Use ES Module syntax for imports/exports. + +Define exports explicitly at the top of the file, right below the imports. + +```ts +import { foo } from "./foo"; +// ... more imports + +export { bar, baz }; + +function bar() { + // function impl. +} + +function baz() { + // function impl. +} + +// not exported +function quz() { + // function impl. +} +``` + +## Tests + +To write tests, use node's built-in test framework. Use the `npm run test` command within the package to run tests. + +Name tests as `[name of tested file].test.ts` and place it into +`packages/[package name]/tests/` directory. All packages are configured to pick +up that file with `npm run test`. + +If you're writing a test in `packages/visual-editor/tests` and the code-to-be-tested +contains signals, use the `packages/visual-editor/tests/signal-watcher.ts` helper +for easy reactivity testing. \ No newline at end of file diff --git a/.changeset/README.md b/.changeset/README.md deleted file mode 100644 index e5b6d8d6a67..00000000000 --- a/.changeset/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Changesets - -Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works -with multi-package repos, or single-package repos to help you version and publish your code. You can -find the full documentation for it [in our repository](https://github.com/changesets/changesets) - -We have a quick list of common questions to get you started engaging with this project in -[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json deleted file mode 100644 index 16f1758c6bf..00000000000 --- a/.changeset/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", - "changelog": "@changesets/cli/changelog", - "commit": ["@changesets/cli/commit", { "skipCI": false }], - "fixed": [], - "linked": [], - "access": "public", - "baseBranch": "main", - "updateInternalDependencies": "patch", - "ignore": [] -} diff --git a/.changeset/honest-ravens-mix.md b/.changeset/honest-ravens-mix.md deleted file mode 100644 index d51c2ac8a58..00000000000 --- a/.changeset/honest-ravens-mix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@breadboard-ai/build": patch ---- - -Allow definition inputs/outputs to be optional diff --git a/.changeset/wicked-impalas-rhyme.md b/.changeset/wicked-impalas-rhyme.md deleted file mode 100644 index 16bb25886c4..00000000000 --- a/.changeset/wicked-impalas-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@breadboard-ai/build-code": patch ---- - -Dereference all (non-circular) references in generated schemas diff --git a/.changeset/yellow-kids-design.md b/.changeset/yellow-kids-design.md deleted file mode 100644 index 46902d0ef7f..00000000000 --- a/.changeset/yellow-kids-design.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@google-labs/agent-kit": patch ---- - -Use new build-code package to implement agent-kit substitute component diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index 73d8087b51e..00000000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,14 +0,0 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the -// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node -{ - "name": "Node.js & TypeScript", - "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye", - "customizations": { - "vscode": { - "extensions": [ - "bierner.markdown-mermaid", - "Google.wireit" - ] - } - } -} diff --git a/.eslintrc.json b/.eslintrc.json index cf507d1b071..e47fadd407e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,4 +1,5 @@ { + "root": true, "env": { "browser": true, "es2021": true @@ -21,6 +22,9 @@ "@typescript-eslint/no-unused-vars": [ "warn", { "argsIgnorePattern": "_.*" } - ] + ], + "@typescript-eslint/no-unused-expressions": "warn", + "@typescript-eslint/no-require-imports": "warn", + "@typescript-eslint/no-unsafe-function-type": "warn" } } diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ccbeb643331..fa0a52f6423 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,41 +1,44 @@ +# References: +# +# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference +# +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/optimizing-pr-creation-version-updates#setting-up-a-cooldown-period-for-dependency-updates + version: 2 updates: - package-ecosystem: "npm" directory: "/" schedule: interval: "daily" - reviewers: - - dglazkov - - aomarks + open-pull-requests-limit: 10 + # Use a cooldown to wait for updates to become stable before applying them. + # This helps to mitigate npm attacks, because the more time has elapsed + # since an attack was published, the more likely it has been discovered and + # removed. Major and minor updates are also further slowed to reduce churn + # and review time. + # + # Note that known security updates always bypass this cooldown. + cooldown: + default-days: 7 + semver-patch-days: 7 + semver-minor-days: 14 + semver-major-days: 21 + groups: + # Minor and patch changes should in theory never be breaking, so let's + # consolidate them into a single PR so that they can be merged together. + minor-and-patch: + applies-to: version-updates + update-types: + - "minor" + - "patch" + exclude-patterns: + # TypeScript doesn't follow semver, because it regularly publishes + # breaking changes (e.g. stricter type-checking) as minor updates. + - typescript - package-ecosystem: "github-actions" directory: ".github/workflows" schedule: interval: "daily" - reviewers: - - dglazkov - - aomarks - - - package-ecosystem: "pip" - directory: "packages/breadboard-python/breadboard_python" - schedule: - interval: "daily" - reviewers: - - dglazkov - - aomarks - - - package-ecosystem: "pip" - directory: "packages/breadboard-python/breadboard_colab" - schedule: - interval: "daily" - reviewers: - - dglazkov - - aomarks - - - package-ecosystem: "devcontainers" - directory: ".devcontainer" - schedule: - interval: "daily" - reviewers: - - dglazkov - - aomarks + cooldown: + default-days: 7 diff --git a/.github/fixtures/fixtures.schema.json b/.github/fixtures/fixtures.schema.json deleted file mode 100644 index d51f1e0fd29..00000000000 --- a/.github/fixtures/fixtures.schema.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "$ref": "#/definitions/Root", - "$schema": "https://json-schema.org/draft-07/schema", - "definitions": { - "Fixture": { - "additionalProperties": false, - "properties": { - "expect": { - "enum": [ - "fail" - ], - "type": "string" - }, - "name": { - "type": "string" - }, - "script": { - "items": { - "type": "string" - }, - "type": "array" - }, - "checkout": { - "type": "boolean" - } - }, - "required": [ - "script", - "name", - "checkout" - ], - "type": "object" - }, - "Root": { - "additionalProperties": false, - "properties": { - "$schema": { - "type": "string" - }, - "fixtures": { - "items": { - "$ref": "#/definitions/Fixture" - }, - "type": "array" - } - }, - "type": "object" - } - } -} diff --git a/.github/fixtures/npx_scripts.json b/.github/fixtures/npx_scripts.json deleted file mode 100644 index c11999081ae..00000000000 --- a/.github/fixtures/npx_scripts.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "$schema": "./fixtures.schema.json", - "fixtures": [ - { - "checkout": false, - "expect": "fail", - "name": "cli@0.5.0 help", - "script": [ - "npx --verbose @google-labs/breadboard-cli@0.5.0 --help" - ] - }, - { - "checkout": false, - "name": "cli@0.5.0 run", - "expect": "fail", - "script": [ - "wget https://raw.githubusercontent.com/$GITHUB_REPOSITORY/$GITHUB_REF_NAME/packages/schema/src/scripts/data/board.json -O board.json", - "npx --verbose @google-labs/breadboard-cli@0.5.0 run packages/schema/src/scripts/data/board.json" - ] - }, - { - "checkout": true, - "name": "npm run test:pack", - "script": [ - "npm install", - "pushd packages/breadboard-cli", - "npm run test:pack" - ] - }, - { - "checkout": true, - "name": "pack && cli run", - "script": [ - "npm install", - "pushd packages/breadboard-cli", - "npm run pack:install", - "cd ~ # this cd is required so the workspace's node_modules aren't available", - "wget https://raw.githubusercontent.com/$GITHUB_REPOSITORY/$GITHUB_REF_NAME/packages/schema/src/scripts/data/board.json -O board.json", - "npx --verbose @google-labs/breadboard-cli run board.json" - ] - }, - { - "checkout": true, - "name": "pack && cli mermaid", - "script": [ - "npm install", - "cd packages/breadboard-cli", - "npm run pack:install", - "cd ~ # this cd is required so the workspace's node_modules aren't available", - "wget https://raw.githubusercontent.com/$GITHUB_REPOSITORY/$GITHUB_REF_NAME/packages/schema/src/scripts/data/board.json -O board.json", - "npx --verbose @google-labs/breadboard-cli mermaid board.json" - ] - }, - { - "checkout": true, - "name": "in-repo cli run", - "script": [ - "npm install", - "cd packages/breadboard-cli", - "npm run build", - "wget https://raw.githubusercontent.com/$GITHUB_REPOSITORY/$GITHUB_REF_NAME/packages/schema/src/scripts/data/board.json -O board.json", - "npx . run board.json" - ] - }, - { - "checkout": true, - "name": "in-repo cli mermaid", - "script": [ - "npm install", - "cd packages/breadboard-cli", - "npm run build", - "wget https://raw.githubusercontent.com/$GITHUB_REPOSITORY/$GITHUB_REF_NAME/packages/schema/src/scripts/data/board.json -O board.json", - "npx . mermaid board.json" - ] - } - ] -} diff --git a/.github/workflows/deploy-website.yml b/.github/workflows/deploy-website.yml deleted file mode 100644 index c3e46bd58bc..00000000000 --- a/.github/workflows/deploy-website.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Deploy Website -on: - # Deploy whenever we merge to main. - push: - branches: ["main"] - - # Allows deploying manually from the Actions tab - workflow_dispatch: - -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages -permissions: - contents: read - pages: write - id-token: write - -# Allow only one concurrent deployment, skipping runs queued between the run -# in-progress and latest queued. However, do NOT cancel in-progress runs as we -# want to allow these production deployments to complete. -concurrency: - group: deploy-website - cancel-in-progress: false - -jobs: - deploy-website: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: npm - - uses: google/wireit@setup-github-actions-caching/v2 - - uses: actions/configure-pages@v5 - - - run: npm ci - - - name: Build production website - working-directory: packages/website - run: npm run build:prod - - - name: Upload website artifact - uses: actions/upload-pages-artifact@v3 - with: - name: breadboard-website - path: packages/website/dist/prod/breadboard - - - name: Deploy to GitHub Pages - uses: actions/deploy-pages@v4 - with: - artifact_name: breadboard-website diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index d801a7ce44b..00000000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,186 +0,0 @@ -name: Docker Build - -on: - push: - branches: - - main - -env: - REGISTRY: ghcr.io - BOARD_SERVER_SQLITE_IMAGE_NAME: board-server-sqlite - BOARD_SERVER_FIRESTORE_IMAGE_NAME: board-server-firestore - ALLOWED_ORIGINS: "" -jobs: - setup: - name: Setup - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Compute short hash - id: short_hash - run: | - SHORT_HASH=$(git rev-parse --short ${{ github.sha }}) - echo "SHORT_HASH=${SHORT_HASH}" >>${GITHUB_OUTPUT} - - - name: Lowercase repository owner - id: lowercase_repo_owner - run: | - echo "REPO_OWNER=${REPO_OWNER,,}" >>${GITHUB_OUTPUT} - env: - REPO_OWNER: "${{ github.repository_owner }}" - - - name: Scoped board server sqlite image name - id: scoped_board_server_sqlite_image_name - run: | - IMAGE_NAME=${{ steps.lowercase_repo_owner.outputs.REPO_OWNER }}/${{ env.BOARD_SERVER_SQLITE_IMAGE_NAME }} - echo "IMAGE_NAME=${IMAGE_NAME}" >>${GITHUB_OUTPUT} - - - name: Board server sqlite image path - id: board_server_sqlite_image_path - run: | - echo "IMAGE_PATH=${{ env.REGISTRY }}/${{ steps.scoped_board_server_sqlite_image_name.outputs.IMAGE_NAME }}" >>${GITHUB_OUTPUT} - - - name: Board server firestore image name - id: board_server_firestore_image_name - run: | - echo "IMAGE_NAME=${{ steps.lowercase_repo_owner.outputs.REPO_OWNER }}/${{ env.BOARD_SERVER_FIRESTORE_IMAGE_NAME }}" >>${GITHUB_OUTPUT} - - - name: Board server firestore image path - id: board_server_firestore_image_path - run: | - echo "IMAGE_PATH=${{ env.REGISTRY }}/${{ steps.board_server_firestore_image_name.outputs.IMAGE_NAME }}" >>${GITHUB_OUTPUT} - - - name: Get package version - id: package_version - run: | - VERSION=$(node -p "require('./packages/board-server/package.json').version") - echo "VERSION=${VERSION}" >> ${GITHUB_OUTPUT} - - outputs: - repo_owner: ${{ steps.lowercase_repo_owner.outputs.REPO_OWNER }} - short_hash: ${{ steps.short_hash.outputs.SHORT_HASH }} - - board_server_sqlite_image_name: ${{ steps.scoped_board_server_sqlite_image_name.outputs.IMAGE_NAME }} - board_server_sqlite_image_path: ${{ steps.board_server_sqlite_image_path.outputs.IMAGE_PATH }} - - board_server_firestore_image_name: ${{ steps.board_server_firestore_image_name.outputs.IMAGE_NAME }} - board_server_firestore_image_path: ${{ steps.board_server_firestore_image_path.outputs.IMAGE_PATH }} - - package_version: ${{ steps.package_version.outputs.VERSION }} - - board-server-sqlite-image: - name: Build board server sqlite image - needs: - - setup - runs-on: ubuntu-latest - - permissions: - contents: read - packages: write - attestations: write - id-token: write - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Registry Auth - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build Image and push - id: push - uses: docker/build-push-action@v6 - with: - context: . - file: ./packages/board-server/Dockerfile - cache-from: | - type=gha,ref=${{ needs.setup.outputs.board_server_sqlite_image_name }} - type=registry,ref=${{ needs.setup.outputs.board_server_sqlite_image_path }} - cache-to: type=gha,mode=max,ref=${{ needs.setup.outputs.board_server_sqlite_image_name }} - push: true - provenance: true - tags: > - ${{ needs.setup.outputs.board_server_sqlite_image_path }}:${{ github.sha }}, - ${{ needs.setup.outputs.board_server_sqlite_image_path }}:${{ needs.setup.outputs.short_hash }}, - ${{ needs.setup.outputs.board_server_sqlite_image_path }}:${{ needs.setup.outputs.package_version }}, - ${{ needs.setup.outputs.board_server_sqlite_image_path }}:latest - build-args: | - STORAGE_BACKEND=sqlite - ALLOWED_ORIGINS=${{ env.ALLOWED_ORIGINS }} - build-contexts: | - breadboard=. - - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v1 - with: - subject-name: ${{ needs.setup.outputs.board_server_sqlite_image_path }} - subject-digest: ${{ steps.push.outputs.digest }} - push-to-registry: true - - board-server-firestore-image: - name: Build board server firestore image - needs: - - setup - runs-on: ubuntu-latest - - permissions: - contents: read - packages: write - attestations: write - id-token: write - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Registry Auth - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build Image and push - id: push - uses: docker/build-push-action@v6 - with: - context: . - file: ./packages/board-server/Dockerfile - cache-from: | - type=gha,ref=${{ needs.setup.outputs.board_server_firestore_image_name }} - type=registry,ref=${{ needs.setup.outputs.board_server_firestore_image_path }} - cache-to: | - type=gha,mode=max,ref=${{ needs.setup.outputs.board_server_firestore_image_name }} - type=registry,mode=max,ref=${{ needs.setup.outputs.board_server_firestore_image_path }} - push: true - provenance: true - tags: > - ${{ needs.setup.outputs.board_server_firestore_image_path }}:${{ github.sha }}, - ${{ needs.setup.outputs.board_server_firestore_image_path }}:${{ needs.setup.outputs.short_hash }}, - ${{ needs.setup.outputs.board_server_firestore_image_path }}:${{ needs.setup.outputs.package_version }}, - ${{ needs.setup.outputs.board_server_firestore_image_path }}:latest - build-args: | - STORAGE_BACKEND=firestore - ALLOWED_ORIGINS=${{ env.ALLOWED_ORIGINS }} - build-contexts: | - breadboard=. - - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v1 - with: - subject-name: ${{ needs.setup.outputs.board_server_firestore_image_path }} - subject-digest: ${{ steps.push.outputs.digest }} - push-to-registry: true \ No newline at end of file diff --git a/.github/workflows/labs-prototypes-ci.yml b/.github/workflows/labs-prototypes-ci.yml index 0f3da4073e1..d712eeac4e7 100644 --- a/.github/workflows/labs-prototypes-ci.yml +++ b/.github/workflows/labs-prototypes-ci.yml @@ -16,26 +16,24 @@ jobs: # - 21.x left here for testing when the node test runnner might be misbahaving python-version: [3.11] + env: + # Enable more verbose log output + # https://github.com/google/wireit?tab=readme-ov-file#environment-variable-reference + WIREIT_LOGGER: metrics + steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: "npm" - - name: Use python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - cache: "pip" - - run: pip install packages/breadboard-python/breadboard_python - - run: pip install packages/breadboard-python/breadboard_colab - uses: google/wireit@setup-github-actions-caching/v2 if: github.event_name != 'pull_request' # For PRs, caching is disabled to ensure a clean build - name: Clean Installing dependencies - run: npm run ci + run: npm ci --ignore-scripts - name: Generating the build run: npm run build diff --git a/.github/workflows/packed-test.yml b/.github/workflows/packed-test.yml deleted file mode 100644 index e9abbbd4578..00000000000 --- a/.github/workflows/packed-test.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: Test packages -on: - push: - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - BOARD: dl_board.json - -jobs: - setup: - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.set-matrix.outputs.matrix }} - steps: - - name: Checkout to repository - uses: actions/checkout@main - with: - sparse-checkout: .github/fixtures - - name: Set matrix data - env: - FILE: .github/fixtures/npx_scripts.json - id: set-matrix - run: echo "matrix=$(jq -c . < $FILE)" >> $GITHUB_OUTPUT - - test: - runs-on: ubuntu-latest - needs: setup - strategy: - fail-fast: false - matrix: - node-version: - - 20.x - fixtures: ${{ fromJson(needs.setup.outputs.matrix).fixtures }} - name: "${{ matrix.fixtures.name }}${{ matrix.fixtures.expect == 'fail' && ' (exected failure)' || '' }} - Node ${{ matrix.node-version }}" - steps: - - name: Setup node ${{ matrix.node-version }} - uses: actions/setup-node@main - with: - node-version: ${{ matrix.node-version }} - - - name: Checkout to repository - uses: actions/checkout@main - if: ${{ matrix.fixtures.checkout }} - - - name: Output YAML arary to temporary script file - run: | - echo "#!/bin/bash -e" > script.sh - echo "set -xv" >> script.sh - echo -e "${{ join(matrix.fixtures.script, '\n') }}" >> script.sh - chmod +x script.sh - - - name: Show script content - run: cat script.sh - - - name: Execute the script - id: execute_script - continue-on-error: ${{ matrix.fixtures.expect == 'fail' }} - run: ./script.sh - - - if: ${{ steps.execute_script.outcome == 'success' && matrix.fixtures.expect == 'fail' }} - run: echo "Test unexpectedly passed" && exit 1 - - - if: ${{ steps.execute_script.outcome == 'failure' && matrix.fixtures.expect == 'fail' }} - run: echo "This is expected to fail" diff --git a/.gitignore b/.gitignore index 5dacdc116f1..ff5917fb810 100644 --- a/.gitignore +++ b/.gitignore @@ -22,7 +22,7 @@ pids all_markdown.md # a file where secrets are stored -secrets.json +secrets.json # Directory for instrumented libs generated by jscoverage/JSCover lib-cov @@ -44,8 +44,7 @@ bower_components .lock-wscript # Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - +build/Release` # Dependency directories node_modules/ jspm_packages/ @@ -91,8 +90,6 @@ typings/ .nuxt dist packages/visual-editor/build -packages/example-boards/build -packages/example-boards/example-boards # Gatsby files .cache/ @@ -135,6 +132,7 @@ packages/example-boards/example-boards *.local.ts *.local.json *.local.md +*.local.txt .wireit *.vsix @@ -144,4 +142,8 @@ packages/example-boards/example-boards lcov.info -packages/data-store/bundled +# VS Code code searches +*.code-search + +# Ignore any remaining instances of sandbox.wasm that might lurk in the tree. +sandbox.wasm \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000000..00db8b0d41c --- /dev/null +++ b/.npmrc @@ -0,0 +1,11 @@ +# Disable automatically running postinstall etc. scripts on install. +# +# This reduces the npm attack surface slightly, because now only +# deps that are actually reachable through our own executed code +# paths have an opportunity to execute code. +# +# If we find a dependency that has a required postinstall step, +# we should create and document our own manual post-install script +# that runs just the required ones. +ignore-scripts=true + diff --git a/.prettierrc b/.prettierrc index 7b761576e23..dd548e7ca72 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,7 @@ { "arrowParens": "always", "printWidth": 80, + "proseWrap": "always", "semi": true, "tabWidth": 2, "trailingComma": "es5", diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index c4989b10265..00000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "type": "breadboard", - "name": "Debug board", - "board": "${workspaceFolder}/${command:AskForBoard}", - "stopOnEntry": true, - "request": "launch" - }, - { - "name": "Attach", - "port": 9229, - "request": "attach", - "skipFiles": ["/**"], - "type": "node" - }, - { - "name": "Python: Current File", - "type": "python", - "request": "launch", - "program": "${file}", - "console": "integratedTerminal", - "args": ["${fileDirname}/${fileBasenameNoExtension}.json"], - "justMyCode": false - }, - { - "type": "node", - "request": "launch", - "name": "Debug AVA test file", - "program": "${workspaceFolder}/node_modules/ava/entrypoints/cli.mjs", - "args": ["${file}"], - "cwd": "${fileDirname}", - "outputCapture": "std", - "console": "integratedTerminal", - "skipFiles": ["/**/*.js"] - }, - { - "type": "node-terminal", - "name": "Board Server: Test", - "request": "launch", - "command": "npm run test", - "cwd": "${workspaceFolder}/packages/board-server" - }, - { - "type": "node-terminal", - "name": "packages/breadboard: test", - "request": "launch", - "command": "rm -rf ${workspaceFolder}/packages/breadboard/.wireit && npm run test", - "cwd": "${workspaceFolder}/packages/breadboard" - } - ] -} diff --git a/DEVELOPING.md b/DEVELOPING.md index 6fbcdbca038..54e04b64a35 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -2,45 +2,17 @@ ## The lay of the land -This repository is configured as a TypeScript monorepo, using Node's built-in [workspace](https://docs.npmjs.com/cli/v9/using-npm/workspaces?v=true) capability. - -Each item within the project lives as an `npm` package, though not all packages are actively published _to_ npm. - -### Packages - -| Package Name | NPM | Description | -| ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | -| _Core_ | | | -| [`@google-labs/breadboard`](./packages/breadboard) | [![Published on npm](https://img.shields.io/npm/v/@google-labs/breadboard.svg?logo=npm)](https://www.npmjs.com/package/@google-labs/breadboard) | The core Breadboard library | -| [`@breadboard-ai/build`](./packages/build) | [![Published on npm](https://img.shields.io/npm/v/@breadboard-ai/build.svg?logo=npm)](https://www.npmjs.com/package/@breadboard-ai/build) | Library for defining boards and node types | -| [`@breadboard-ai/visual-editor`](./packages/visual-editor) | _Unpublished_ | The source code for the Breadboard Visual Editor | -| _Kits_ | | | -| [`@google-labs/agent-kit`](./packages/agent-kit) | [![Published on npm](https://img.shields.io/npm/v/@google-labs/agent-kit.svg?logo=npm)](https://www.npmjs.com/package/@google-labs/agent-kit) | Breadboard kit for building agent-like experiences | -| [`@google-labs/core-kit`](./packages/core-kit) | [![Published on npm](https://img.shields.io/npm/v/@google-labs/core-kit.svg?logo=npm)](https://www.npmjs.com/package/@google-labs/core-kit) | Breadboard kit for foundational board operations like `map` and `invoke` | -| [`@google-labs/gemini-kit`](./packages/gemini-kit) | [![Published on npm](https://img.shields.io/npm/v/@google-labs/gemini-kit.svg?logo=npm)](https://www.npmjs.com/package/@google-labs/gemini-kit) | Breadboard kit for working with the Gemini API | -| [`@google-labs/google-drive-kit`](./packages/google-drive-kit) | [![Published on npm](https://img.shields.io/npm/v/@google-labs/google-drive-kit.svg?logo=npm)](https://www.npmjs.com/package/@google-labs/google-drive-kit) | Breadboard kit for working with Google Drive | -| [`@google-labs/json-kit`](./packages/json-kit) | [![Published on npm](https://img.shields.io/npm/v/@google-labs/json-kit.svg?logo=npm)](https://www.npmjs.com/package/@google-labs/json-kit) | Breadboard kit for working with JSON in boards | -| [`@google-labs/template-kit`](./packages/template-kit) | [![Published on npm](https://img.shields.io/npm/v/@google-labs/template-kit.svg?logo=npm)](https://www.npmjs.com/package/@google-labs/template-kit) | Breadboard kit to help with templating | -| [`@google-labs/palm-kit`](./packages/palm-kit) | [![Published on npm](https://img.shields.io/npm/v/@google-labs/palm-kit.svg?logo=npm)](https://www.npmjs.com/package/@google-labs/palm-kit) | Breadboard kit for working with the PaLM API in boards | -| [`@exadev/breadboard-kits`](https://github.com/ExaDev-io/breadboard-kits) | [![Published on npm](https://img.shields.io/npm/v/@exadev/breadboard-kits?logo=npm)](https://www.npmjs.com/package/@exadev/breadboard-kits) | A variety of utilities, general purpose nodes, and kits specific scenarios | -| _Tools & Support Libraries_ | | | -| [`@google-labs/breadboard-cli`](./packages/breadboard-cli) | [![Published on npm](https://img.shields.io/npm/v/@google-labs/breadboard-cli.svg?logo=npm)](https://www.npmjs.com/package/@google-labs/breadboard-cli) | Command-line tool for generating, running, and debugging boards | -| [`@breadboard-ai/import`](./packages/import) | [![Published on npm](https://img.shields.io/npm/v/@breadboard-ai/import.svg?logo=npm)](https://www.npmjs.com/package/@breadboard-ai/import) | Library for importing boards from an OpenAPI spec | -| _Internal/Experiments_ | | | -| [`@breadboard-ai/manifest`](./packages/manifest) | _Unpublished_ | An internal tool that generates a JSON list of board files | -| [`@breadboard-ai/python-wasm`](./packages/python-wasm) | _Unpublished_ | Implementation of runPython component using WASM (Web Assembly) | -| [`@google-labs/breadboard-python`](./packages/breadboard-python) | _Unpublished_ | A library that allows developers to define Breadboards with Python | -| [`@google-labs/breadboard-schema`](./packages/breadboard-schema) | _Unpublished_ | An internal tool that generates a JSON schema from the Breadboard TypeScript types | -| [`@google-labs/breadboard-website`](./packages/website) | _Unpublished_ | The documentation website for Breadboard | -| [`@google-labs/connection-server`](./packages/connection-server) | _Unpublished_ | Used for handling connections to third party services | -| [`@google-labs/discovery-types`](./packages/discovery-types) | _Unpublished_ | Library which generates TypeScript declarations from the PaLM API Discovery Document | -| [`@google-labs/node-nursery-web`](./packages/node-nursery-web) | _Unpublished_ | A place for experimenting with board nodes that aren't yet ready for their own package (web specific) | -| [`@google-labs/node-nursery`](./packages/node-nursery) | _Unpublished_ | A place for experimenting with board nodes that aren't yet ready for their own package (general) | -| [`@google-labs/node-proxy-server`](./packages/node-proxy-server) | _Unpublished_ | Library that allows running nodes remotely | +This repository is configured as a TypeScript monorepo, using Node's built-in +[workspace](https://docs.npmjs.com/cli/v9/using-npm/workspaces?v=true) +capability. + +Each item within the project lives as an `npm` package, though not all packages +are actively published _to_ npm. ## Building a package -We use [Wireit](https://github.com/google/wireit) as the build tool for the monorepo. +We use [Wireit](https://github.com/google/wireit) as the build tool for the +monorepo. All packages within the monorepo have a similar structure: @@ -62,7 +34,8 @@ All packages within the monorepo have a similar structure: Project source files go into the `src` directory, while tests go into `tests`. -The TypeScript build is configured to produce a `dist` directory in the root of each package. This is the directory that is published to `npm`. +The TypeScript build is configured to produce a `dist` directory in the root of +each package. This is the directory that is published to `npm`. ## Getting started @@ -86,41 +59,34 @@ To run all tests: npm run test ``` -Most of the time, you will likely want to bring up the Breadboard Web UI. To do so, run the `w` command: +Most of the time, you will likely want to bring up the Breadboard Web UI. To do +so, run the `dev` command: ```bash -npm run w +npm run dev ``` -To start a doc site server: +Occasionally, there will be changes that will require a full rebuild with +installing new packages, etc. -```bash -npm run d -``` +When you find your repo in a funky state, use `npm run clean`. It will delete +all build artifacts and bring the repo back to the pristine state, allowing you +to restart with `npm i` and all those things. -To start a board server and a Breadboard Web UI: - -```bash -npm run s -``` - -Occasionally, there will be changes that will require a full rebuild with installing new packages, etc. - -When you find your repo in a funky state, use `npm run clean`. It will delete all build artifacts and bring the repo back to the pristine state, allowing you to restart with `npm i` and all those things. - -> [!CAUTION] -> If you have any local files that you have saved in the tree, they will be deleted. +> [!CAUTION] If you have any local files that you have saved in the tree, they +> will be deleted. ```bash npm run clean - ``` ## Creating a new package To create a new package: -:one: Copy a template project as a new directory under `packages`. For example, if the name of your new prototyping project is `awesome-ai-game`, you would run something like this: +:one: Copy a template project as a new directory under `packages`. For example, +if the name of your new prototyping project is `awesome-ai-game`, you would run +something like this: ```bash cp -rf templates/blank packages/awesome-ai-game @@ -128,10 +94,12 @@ cp -rf templates/blank packages/awesome-ai-game :two: Replace the following placeholders: -- `{{name}}` -- specify the name of the package. It usually matches the name of the directory you just created, like `awesome-ai-game`. +- `{{name}}` -- specify the name of the package. It usually matches the name of + the directory you just created, like `awesome-ai-game`. - `{{description}}` -- describe the nature of the project in one sentence. -:three: Add project as a reference to the `tsconfig.json`. For example, for `awesome-ai-game`: +:three: Add project as a reference to the `tsconfig.json`. For example, for +`awesome-ai-game`: ```json { @@ -141,7 +109,8 @@ cp -rf templates/blank packages/awesome-ai-game } ``` -:four: Verify that you have the right setup. Run `npm i` and `npm run build` and make sure that the new package shows up in the build log. Then try to run it: +:four: Verify that you have the right setup. Run `npm i` and `npm run build` and +make sure that the new package shows up in the build log. Then try to run it: ```bash cd packages/awesome-ai-game @@ -152,13 +121,18 @@ You should see `code goes here` as output. :five: Build whatever it is you've dreamed up! -The new package is configured as a private package by default. If you would like to publish it to `npm`, flip the `private` flag to `true` in `package.json`. +The new package is configured as a private package by default. If you would like +to publish it to `npm`, flip the `private` flag to `true` in `package.json`. ## Working on your project -If everything is set up well, you will spend most of your time tinkering inside of your package. +If everything is set up well, you will spend most of your time tinkering inside +of your package. -We recommend opening [VSCode](https://code.visualstudio.com/) in the package directory to reduce the amount of clutter. When you run `npm run` inside of your package directory, it will automatically scope the build to only dependencies in your package. +We recommend opening [VSCode](https://code.visualstudio.com/) in the package +directory to reduce the amount of clutter. When you run `npm run` inside of your +package directory, it will automatically scope the build to only dependencies in +your package. To build your package: @@ -172,13 +146,20 @@ To test your package: npm test ``` -You can add more commands to `package.json` and invoke them using `npm run `. +You can add more commands to `package.json` and invoke them using +`npm run `. -To add a new dependency for your package, just run `npm i ` in your package working directory. +To add a new dependency for your package, just run `npm i ` in +your package working directory. -When you need to refer to other packages in the monorepo, you will need to do a bit of manual wiring. +When you need to refer to other packages in the monorepo, you will need to do a +bit of manual wiring. -In your project's `package.json` edit the contents of `dependencies` (or `devDependencies`) to add the entry for the package on which you want this package to depend. For example, if we're adding a dependency on the package called `"@google-labs/ai-game-engine"` that also resides in this monorepo, we will do: +In your project's `package.json` edit the contents of `dependencies` (or +`devDependencies`) to add the entry for the package on which you want this +package to depend. For example, if we're adding a dependency on the package +called `"@google-labs/ai-game-engine"` that also resides in this monorepo, we +will do: ```json "dependencies": { @@ -188,11 +169,15 @@ In your project's `package.json` edit the contents of `dependencies` (or `devDep ## Testing -Out of the box, the project template is configured to use [ava](https://github.com/avajs/ava) for testing. You can pick a different test framework. Just make sure to configure your `package.json` to point to it, so that `npm` can run it. +Out of the box, the project template is configured to use +[ava](https://github.com/avajs/ava) for testing. You can pick a different test +framework. Just make sure to configure your `package.json` to point to it, so +that `npm` can run it. ## Cleaning stuff -Sometimes, TypeScript Compiler or Wireit (or both!) gets confused, and the only way forward is to clean up the build artifacts and start over. To do that, run: +Sometimes, TypeScript Compiler or Wireit (or both!) gets confused, and the only +way forward is to clean up the build artifacts and start over. To do that, run: ```bash npm run clean @@ -215,18 +200,24 @@ doesn't comply with the license.) ## TypeScript Developer Happy Path -This section describes that we generally use within the Breadboard team, and it's probably what will give you the most comfortable developer experience in this repo. +This section describes that we generally use within the Breadboard team, and +it's probably what will give you the most comfortable developer experience in +this repo. ### VSCode -Get [VSCode](https://code.visualstudio.com/). There are tons of other editors, but VSCode has likely the most seamless TypeScript integration. +Get [VSCode](https://code.visualstudio.com/). There are tons of other editors, +but VSCode has likely the most seamless TypeScript integration. -Install “ESLint” and “Prettier” extensions. TypeScript support is built-in by default. +Install “ESLint” and “Prettier” extensions. TypeScript support is built-in by +default. - “ESLint” – provides live commentary on the quality of your code. - “Prettier” – will make your code look pretty automatically. -Tweak the settings to your liking. The most important one is to format-on-save, so that you never need to worry about formatting TypeScript ever again. Here is what we have: +Tweak the settings to your liking. The most important one is to format-on-save, +so that you never need to worry about formatting TypeScript ever again. Here is +what we have: ``` "editor.rulers": [80] <-- Draws a nice ruler at 80 columns @@ -236,14 +227,23 @@ Tweak the settings to your liking. The most important one is to format-on-save, "editor.formatOnSave": true, <-- format with Prettier on save ``` -Use the built-in terminal (Ctrl+`). For convenience, split the TERMINAL and PROBLEMS tabs horizontally. +Use the built-in terminal (Ctrl+`). For convenience, split the TERMINAL and +PROBLEMS tabs horizontally. -This setup creates a really nice separation of the workspace: the top part is where we write code, and the bottom part is where we see if it works. As we type, the problems come and go in the bottom-right window. When we are ready to try running my code, we switch to the terminal and run it from there. +This setup creates a really nice separation of the workspace: the top part is +where we write code, and the bottom part is where we see if it works. As we +type, the problems come and go in the bottom-right window. When we are ready to +try running my code, we switch to the terminal and run it from there. -Because TypeScript is built-in, TypeScript errors will show up live in the PROBLEMS window as well, which is super-convenient. -Learn keyboard shortcuts. Ctrl+P (Cmd+P) and Ctrl+Shift+P (Cmd+Shift+P) are likely the most important ones. +Because TypeScript is built-in, TypeScript errors will show up live in the +PROBLEMS window as well, which is super-convenient. Learn keyboard shortcuts. +Ctrl+P (Cmd+P) and Ctrl+Shift+P (Cmd+Shift+P) are likely the most important +ones. -Occasionally, VSCode’s built-in TypeScript machinery gets into a confused state. For this purpose, there’s a “TypeScript: Restart TS Server“ command available via Cmd/Ctrl+Shift+P. We can also use the “Developer: Reload Windows“ command to flush out the gremlins. +Occasionally, VSCode’s built-in TypeScript machinery gets into a confused state. +For this purpose, there’s a “TypeScript: Restart TS Server“ command available +via Cmd/Ctrl+Shift+P. We can also use the “Developer: Reload Windows“ command to +flush out the gremlins. ### Workflow @@ -251,129 +251,39 @@ The dev cycle is: - Open the directory of the package (or several of them) in VSCode - Write some code -- Make ESLint and TypeScript live-compiler happy (no errors show up in the PROBLEMS window) -- Run `npm run build` to build the code. For packages like the Visual Editor we generally use `npm run dev`, which often provides a live reload feature in the browser. -- Run your code with `node .` or whatever is the right way to run it. For convenience, create an [npm script](https://docs.npmjs.com/cli/v9/using-npm/scripts) to combine building and running. +- Make ESLint and TypeScript live-compiler happy (no errors show up in the + PROBLEMS window) +- Run `npm run build` to build the code. For packages like the Visual Editor we + generally use `npm run dev`, which often provides a live reload feature in the + browser. +- Run your code with `node .` or whatever is the right way to run it. For + convenience, create an + [npm script](https://docs.npmjs.com/cli/v9/using-npm/scripts) to combine + building and running. - Go to the “Write some code” step. ### Build system -This is a monorepo, which in Node.js vernacular means that it is a flat list of npm packages that are all hosted in the same git repository. +This is a monorepo, which in Node.js vernacular means that it is a flat list of +npm packages that are all hosted in the same git repository. -The main reason we need to run `npm run build` is because in the monorepo, we need to compute the dependency graph before compiling TypeScript to Javascript, and that is not something that comes standard with the TypeScript compiler. +The main reason we need to run `npm run build` is because in the monorepo, we +need to compute the dependency graph before compiling TypeScript to Javascript, +and that is not something that comes standard with the TypeScript compiler. #### Front-end -[Vite](https://vitejs.dev/) is currently brought up in the `visual-editor` package. Use it as a template for other front-end TypeScript packages. +[Vite](https://vitejs.dev/) is currently brought up in the `visual-editor` +package. Use it as a template for other front-end TypeScript packages. ## Sending PRs -This repo protects the `main` branch, which means all changes must go through a GitHub PR. This enforces that all tests pass and packages builds before any change lands, and provides an opportunity for code review. +This repo protects the `main` branch, which means all changes must go through a +GitHub PR. This enforces that all tests pass and packages builds before any +change lands, and provides an opportunity for code review. -> [!TIP] -> The [GitHub CLI](https://cli.github.com/) makes it easy to send PRs by +> [!TIP] The [GitHub CLI](https://cli.github.com/) makes it easy to send PRs by > typing `gh pr create`. You can use the `--fill` or `-f` flag to automatically -> populate the title and description from your commits. See the [create command -> documentation](https://cli.github.com/manual/gh_pr_create) for more -> information. - -### Changesets - -This repo uses [Changesets](https://github.com/changesets/changesets) to ease the burden of releasing of NPM packages. The benefits are that it publishes multiple packages at once, understands the dependencies between all packages in the monorepo, automatically updates the `package.json` and `CHANGELOG.md` files, and automatically creates release tags. - -> [!TIP] -> If you need to publish NPM packages, see the [Publishing NPM -> packages](#publishing-npm-packages) section below. - -After sending a PR, you may receive a comment from [**changeset-bot**](https://github.com/apps/changeset-bot) that looks like this: - -![changeset-bot comment](https://user-images.githubusercontent.com/11481355/66183943-dc418680-e6bd-11e9-998d-e43f90a974bd.png) - -This bot is telling you that your PR does not contain a [Changeset file](https://github.com/changesets/changesets/blob/main/docs/detailed-explanation.md). Changeset files are how Changesets understands which packages need to be released at any given time, along with the kind of version bump that is needed for them. - -The easiest way to create a Changeset file for your PR is to run this command from the root of the monorepo: - -``` -npx changeset -``` - -This command will prompt you with an interactive list of packages. Select the packages that the PR affects and indicate whether the changes are [semver](https://semver.org/) `major` (breaking), `minor` (new features), or `patch` (bug fixes). - -> [!NOTE] -> If your change only affects **unpublished** packages, then you can -> safely skip adding a changeset file and ignore the bot. - -Then just push the generated changeset file to your PR! - -## Publishing NPM packages - -To publish an NPM package, you have to be a Googler. This is unlikely -to change in the future. Having said that, here are the steps to publish a -package. - -1. At the root of the repository, ensure you are synchronized to the tip of - `main` and create a new release branch. - - ```bash - git checkout main - git pull - git checkout -b release - ``` - -2. Use the Changesets - [version](https://github.com/changesets/changesets/blob/main/docs/command-line-options.md#version) - command to find all packages that need releasing and automatically update - their `package.json` and `CHANGELOG.md` files. Note that Changesets - automatically bumps the semver constraints for dependent packages when - needed, so there is no need to manually edit any `package.json` files. - - ```bash - npx changeset version - ``` - - > [!NOTE] - > Sometimes, the command may fail with a fairly cryptic error like "TypeError: Cannot destructure property 'packageJson' of 'undefined' as it is undefined.". This typically means that a package was renamed sometime between the last release and now. To fix, look through the `.md` files in the `./.changeset` directory, and remove all lines that reference the package by its - > old name. - -3. Check what is planned to be published by looking at the latest commit which - Changesets created in the previous step. Make sure it looks reasonable, and - send a PR with the changes so that others can see what will be published. - - ```bash - git show - gh pr create -f # or git push if you don't have the gh tools - ``` - -4. Sign in to NPM: - - ```bash - npm adduser - ``` - -5. Generate a token for the Google NPM release proxy registry. Running the - command below will open a browser window. Select _24 hour temporary token_ - after which the command should exit by itself. - - ```bash - npm login --registry https://wombat-dressing-room.appspot.com - ``` - -6. Wait for the PR from step 3 to pass CI. - -7. Use the Changesets - [publish](https://github.com/changesets/changesets/blob/main/docs/command-line-options.md#publish) - command to publish all changes and generate release tags (e.g. - `@google-labs/breadboard@0.8.0`). - - ```bash - npx changeset publish - ``` - -8. Push the release tags added in step 7 to GitHub so that they are associated - with the commit from step 2. - - ```bash - git push --follow-tags - ``` - -9. Merge the PR from step 3. +> populate the title and description from your commits. See the +> [create command documentation](https://cli.github.com/manual/gh_pr_create) for +> more information. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000000..0808c9e8345 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM node:20-slim +WORKDIR /breadboard + +COPY / . +RUN npm clean-install + +ENV NODE_ENV="production" +ARG VITE_BOARD_SERVICE="drive:" + +WORKDIR packages/unified-server +RUN npm run build + +CMD ["node", "dist/src/main.js"] diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000000..4648e5e3a5f --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,4 @@ +To report a security issue, please use [https://g.co/vulnz](https://g.co/vulnz). +We use g.co/vulnz for our intake, and do coordination and disclosure here on +GitHub (including using GitHub Security Advisory). The Google Security Team will +respond within 5 working days of your report on g.co/vulnz. diff --git a/boards/README.md b/boards/README.md deleted file mode 100644 index de5ab54cf47..00000000000 --- a/boards/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# Boards - -This directory contains boards for Breadboard. Each board is a demonstration of what how you can use Breadboard to solve a particular problem. Many of these boards can be included directly inside boards. - -## Running a Board - -Note: If you have not already installed the breadboard CLI, you can do so by running the following command: - -```bash -npm install -g @breadboard/breadboard-cli -``` - -or, if you are running from the monorepo: - -```bash -npm i -npm run build -npm i -``` - -You need to install all the deps, then build the CLI, then install the deps again to install the command. If you plan to run from the mono repo, prepend `npx` to the commands below. - -To run a board, run the following command from the root of the repository: - -```bash -breadboard run boards/ -``` - -To run from the UI: - -```bash -breadboard debug boards/ -``` - -## Creating a new Board - -To create a new board, create a new directory in this directory. The name of the directory should be the name of the board and should contain a `README.md` file that describes the board and a TypeScript file that contains the code for the board. - -TODO: Add more details here. - -## List of Boards - -### Use Cases - -A use case board is something that can be directly integrated into a Breadboard to solve a particular problem. These boards are designed to be used as-is and have no dependencies on other boards. - -- [Fetch RSS Feed](./use-case/fetch-rss/README.md) -- [Fetch ATOM Feed](./use-case/fetch-atom/README.md) -- [Search Google](./use-case/search-google/README.md) -- [Generate Embedding](./use-case/generate-embedding/README.md) -- [Generate Text](./use-case/generate-text/README.md) -- [Convert String to JSON](./use-case/convert-string-to-json/README.md) - -### Concepts - -A concept board is something that demonstrates a particular concept in Breadboard, it might not be something that can be used directly in an application, but it is a good starting point. - -- [Accumulating Context](./concept/accumulating-context/README.md) -- [Few-Shot Learning](./concept/few-shot/README.md) -- [RAG Query](./concept/rag-query/README.md) diff --git a/boards/tools/openapi/README.md b/boards/tools/openapi/README.md deleted file mode 100644 index c05676f8ed3..00000000000 --- a/boards/tools/openapi/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Generate a board from an OpenAPI spec - -## Running the Board - -```bash -breadboard run boards/tools/openapi/openapi.js --kit @google-labs/core-kit -i "{\"url\":\"https://api.apis.guru/v2/specs/apis.guru/2.2.0/openapi.json\"}" -``` - -### Inputs - -- url - The url to the OpenAPI spec (JSON only for now) - -### Outputs - -- board - The generated board that has a list of boards. - -## Compiling the board - -`breadboard make boards/tools/openapi/--kit @google-labs/core-kit.js > boards/tools/openapi/index.json` diff --git a/boards/tools/openapi/openapi-toolworker.json b/boards/tools/openapi/openapi-toolworker.json deleted file mode 100644 index d1e8897157e..00000000000 --- a/boards/tools/openapi/openapi-toolworker.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "title": "Open API", - "description": "A blank board. Use it to start a new board", - "version": "0.0.1", - "edges": [ - { - "from": "invoke-d54f531b", - "to": "runJavascript-328fbe28", - "out": "*", - "in": "" - }, - { - "from": "toolWorker-4f7d0530", - "to": "output-2", - "out": "text", - "in": "text" - }, - { - "from": "runJavascript-328fbe28", - "to": "toolWorker-4f7d0530", - "out": "result", - "in": "tools" - }, - { - "from": "input-69e36921", - "to": "toolWorker-4f7d0530", - "out": "context", - "in": "context" - }, - { - "from": "input-69e36921", - "to": "invoke-d54f531b", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "text" - } - } - } - }, - "metadata": { - "visual": { - "x": 343, - "y": 29 - } - } - }, - { - "id": "invoke-d54f531b", - "type": "invoke", - "configuration": { - "url": "https://bread-boards.glitch.me/open-ai-openapi.json", - "$board": { - "kind": "board", - "path": "file://fsapi~openapi/openapi.json" - }, - "builderPath": "https://bread-boards.glitch.me/request-builder.json" - }, - "metadata": { - "visual": { - "x": -592, - "y": 105 - } - } - }, - { - "id": "runJavascript-328fbe28", - "type": "runJavascript", - "configuration": { - "code": "function convertToToolsList(args) {\n const mapper = (i) => { \n return i.board.board;\n };\n\n return Object.values(args).map(mapper);\n};", - "name": "convertToToolsList" - }, - "metadata": { - "visual": { - "x": -339, - "y": 112 - } - } - }, - { - "id": "toolWorker-4f7d0530", - "type": "toolWorker", - "metadata": { - "visual": { - "x": -8, - "y": -42 - } - }, - "configuration": { - "instruction": "You are a computer return JSON" - } - }, - { - "id": "input-69e36921", - "type": "input", - "metadata": { - "visual": { - "x": -381, - "y": -135 - } - }, - "configuration": { - "schema": { - "properties": { - "context": { - "type": "string", - "title": "Context", - "examples": [ - "Generate an embedding for Hello World" - ], - "format": "multiline", - "default": "Generate an embedding for Hello World" - } - }, - "type": "object", - "required": [] - } - } - } - ] -} \ No newline at end of file diff --git a/boards/tools/openapi/openapi.js b/boards/tools/openapi/openapi.js deleted file mode 100644 index 288fb7a1850..00000000000 --- a/boards/tools/openapi/openapi.js +++ /dev/null @@ -1,531 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { base, board, code } from "@google-labs/breadboard"; -import { core } from "@google-labs/core-kit"; - -const metaData = { - title: "Create a board from an Open API spec", - description: "Converts an Open API spec to a board.", - version: "0.0.3", -}; - -const validateIsOpenAPI = code(({ json }) => { - if ("openapi" in json == false) { - throw new Error("Not an Open API spec."); - } - - if ("servers" in json == false) { - throw new Error("No servers in Open API spec."); - } - - if ("paths" in json == false) { - throw new Error("No paths in Open API spec."); - } - - return { json }; -}); - -/* - Generate a list of API operations from the given Open API spec that will be used to create the board of boards. -*/ -const generateAPISpecs = code(({ json, context, builderPath }) => { - const { paths, info } = json; - const baseUrl = json.servers[0].url; - - /* - If there is no operation ID, we need to generate one from the path, but format it like a JS function name. - */ - const inferOperationId = (path, method) => { - let newName = path - .split("/") - .map((part) => - part.length == 0 ? part : part[0].toUpperCase() + part.slice(1) - ) - .join("") - .replace(/[.-]/g, "") // Remove dashes and dots - .replace(/[{}]/g, ""); // Remove curly braces (need to improve this) - - return `${method}${newName}`; - }; - - const apis = Object.entries(paths) - .map(([key, value]) => { - // Parse parameters on the path - let pathParameters = []; - if ("parameters" in value) { - pathParameters = value.parameters.map((param) => { - // We can only manage reference objects for now. - if ("$ref" in param) { - if (param.$ref.startsWith("#") == false) { - return undefined; - } - - const pathParts = param.$ref.replace(/^#\//, "").split("/"); - let obj = json; - - for (const part of pathParts) { - obj = obj[part]; - } - - return obj; - } else { - return param; - } - }); - } - - return Object.keys(value) - .filter((method) => ["post", "get"].includes(method)) - .map((method) => { - // Operation ID might not exist. - const operationId = - value[method].operationId || - inferOperationId(key, method, value[method]); - - const data = value[method]; - - // All parameters, path or query are held in the parameters array ( but might be a reference) - const parameters = - "parameters" in data == false - ? [] - : data.parameters.map((param) => { - // We can only manage reference objects for now. - if ("$ref" in param) { - if (param.$ref.startsWith("#") == false) { - return undefined; - } - - const pathParts = param.$ref.replace(/^#\//, "").split("/"); - let obj = json; - - for (const part of pathParts) { - obj = obj[part]; - } - - return obj; - } else { - return param; - } - }); - - parameters.push(...pathParameters); - - const requestBody = - "requestBody" in data == false - ? undefined - : Object.entries(data.requestBody.content) - .map(([contentType, reqeustParams]) => { - // We can only manage reference objects for now. - if ("$ref" in reqeustParams.schema) { - if (reqeustParams.schema.$ref.startsWith("#") == false) { - return undefined; - } - - const pathParts = reqeustParams.schema.$ref - .replace(/^#\//, "") - .split("/"); - let obj = json; - - for (const part of pathParts) { - obj = obj[part]; - } - - if ("description" in obj == false) { - obj.description = `Request POST data (format: ${contentType})`; - } - return { [contentType]: { schema: obj } }; - } - return { [contentType]: reqeustParams }; - }) - .reduce((acc, curr) => { - return { ...acc, ...curr }; - }, {}); - - // We will need to hook up `secrets` to this somehow. - let secrets = undefined; - // We can only support Bearer tokens for now. - if ("components" in json && "securitySchemes" in json.components) { - // Check to see if global security is defined, it's the same type and && it is a bearer token. - const bearerSecurity = Object.entries( - json.components.securitySchemes - ).find(([securityMethodKey, securityValue]) => { - const security = json.security.find((item) => { - return securityMethodKey in item; - }); - - return ( - security && - securityValue.type == "http" && - securityValue.scheme == "bearer" - ); - }); - - if (bearerSecurity != undefined) { - secrets = bearerSecurity; - } - } - - const headers = { - operationId, - url: baseUrl.replace(/\/$/, "") + key, - method: method.toUpperCase(), - description: data.description, - summary: data.summary, - parameters, - requestBody, - secrets, - info, - context, - builderPath, - }; - - return headers; - }) - .flat(); - }) - .flat(); - - return { list: apis }; -}); - -/* - Returns a lambda that will make a request to the given API. This is used in the `core.map` to create a board of boards for each API exposed on the OpenAPI spec. -*/ -const createSpecBoard = board((apiSpec) => { - const output = base.output({}); - - const createBoardInputs = code(({ item }) => { - const { parameters } = item; - const nodes = []; - - const inputNode = { - id: `input`, - type: `input`, - configuration: { - schema: { - type: "object", - properties: parameters.reduce((params, param) => { - const schema = { ...param.schema }; - schema.title = param.name; - schema.description = param.description || param.schema.title; - - if (param.required) { - if ("default" in param == false) { - schema.default = undefined; - } else { - schema.default = param.default; - } - } else { - schema.default = param.default || null; - } - - if (param.in == "query" || param.in == "path") { - params[param.name] = schema; - } - - return params; - }, {}), - }, - }, - }; - - nodes.push(inputNode); - - nodes.push({ id: "output", type: "output" }); - - const edges = parameters.map((param) => { - return { - from: `input`, - out: param.name, - to: "output", - in: param.name, - optional: !param.required, - }; - }); - - if ("secrets" in item && item.secrets != undefined) { - const apiKeyName = `${item.info.title - .replace(/[^a-zA-Z0-9]+/g, "_") - .toUpperCase()}_KEY`; - - nodes.push({ - id: "input-secrets", - type: "secrets", - configuration: { - keys: [apiKeyName], - }, - }); - - edges.push({ - from: "input-secrets", - out: apiKeyName, - to: "output", - in: apiKeyName, - }); - } - - if (nodes.length == 0) { - nodes.push({ id: "input", type: "input" }); - } - - if (edges.length == 0) { - edges.push({ from: `input`, out: "*", to: "output", in: "" }); - } - - const graph = { - title: `API Inputs for ${item.operationId}`, - url: "#", - nodes, - edges, - }; - - return { graph }; - }); - - const graphInputs = apiSpec.item.to( - createBoardInputs({ - $id: "createBoardInputs", - }) - ); - - const APIEndpoint = board((input) => { - const { item, graph } = input; - - const toAPIInputs = code((item) => { - debugger; - console.log("API Inputs", item); - return { api_inputs: item }; - }); - - const getBuilderPath = code(({ item }) => { - return { - path: item.builderPath, - $board: item.builderPath, - context: item.context, - text: item.context, - theSchema: item.requestBody["application/json"].schema, - }; - }); - - const createRequestBody = code(({ text, input }) => { - debugger; - return { requestBody: text, input }; - }); - - const generateRequestBodyFromSchema = core.invoke({ - $id: "generateRequestBodyFromSchema", - }); - - getBuilderPath({ $id: "getBuilderPath", item }).to( - generateRequestBodyFromSchema - ); - - const requestBody = generateRequestBodyFromSchema.text.to( - createRequestBody({ - $id: "createRequestBody", - input, - }) - ); - - const mergedInputs = core - .invoke({ - $id: "mergeInputs", - item, - graph, - }) - .to(toAPIInputs); - - const api_inputs = toAPIInputs({ - $id: "toAPIInputs", - item, - ...mergedInputs, - requestBody: requestBody.requestBody, - }); - - const output = base.output({}); - - const createFetchParameters = code(({ item, api_inputs }) => { - const { method, parameters, secrets, requestBody } = item; - debugger; - console.log("API Inputs", item); - - let { url } = item; - - const queryStringParameters = {}; - - if (typeof api_inputs == "string") { - api_inputs = JSON.parse(api_inputs); - } - - if ( - parameters != undefined && - parameters.length > 0 && - api_inputs == undefined - ) { - throw new Error( - `Missing input for parameters ${JSON.stringify(parameters)}` - ); - } - - for (const param of parameters) { - if (api_inputs && param.name in api_inputs == false && param.required) { - throw new Error(`Missing required parameter ${param.name}`); - } - - if (api_inputs && param.name in api_inputs == false) { - // Parameter is not required and not in input, so we can skip it. - continue; - } - - if (param.in == "path") { - // Replace the path parameter with the value from the input. - url = url.replace(`{${param.name}}`, api_inputs[param.name]); - } - - if (param.in == "query") { - queryStringParameters[param.name] = api_inputs[param.name]; - } - } - - // If the method is POST or PUT, then we need to add the requestBody to the body. - - // We are going to want to add in the secret somehow - const headers = {}; - - // Create the query string - const queryString = Object.entries(queryStringParameters) - .map(([key, value]) => { - return `${key}=${value}`; - }) - .join("&"); - - if (queryString.length > 0) { - url = `${url}?${queryString}`; - } - - // Many APIs will require an authentication token but they don't define it in the Open API spec. - if (secrets != undefined && secrets[1].scheme == "bearer") { - const envKey = `${item.info.title - .replace(/[^a-zA-Z0-9]+/g, "_") - .toUpperCase()}_KEY`; - const envValue = api_inputs[envKey]; - - headers["Authorization"] = `Bearer ${envValue}`; - } - - let body = undefined; - - if (requestBody) { - // We know the method needs a request Body. - // Find the first input that matches the valid required schema of the API. - let requestContentType; - - // We can only handle JSON - if ("requestBody" in api_inputs) { - body = - typeof api_inputs["requestBody"] == "string" - ? JSON.parse(api_inputs["requestBody"]) - : api_inputs["requestBody"]; - requestContentType = "application/json"; - } - - if (body == undefined) { - throw new Error( - `Missing required request body for ${JSON.stringify(requestBody)}` - ); - } - - headers["Content-Type"] = requestContentType; - } - return { url, method, headers, body, queryString }; - }); - - return createFetchParameters({ - $id: "createFetchParameters", - item, - api_inputs, - }) - .to(core.fetch()) - .response.as("api_json_response") - .to(output); - }); - - apiSpec.item.to(output); - graphInputs.to(output); - apiSpec.item.to(APIEndpoint); - graphInputs.to(APIEndpoint); - apiSpec.builderPath.to(APIEndpoint); - - return apiSpec.item.to(APIEndpoint).as("board").to(output); -}); - -/* - Because we need a nice interface on the board that calls this, we need to convert from a list to an object. This will then enable something like `core.invoke().API_NAME_YOU_WANT_CALL`. -*/ -const convertBoardListToObject = code(({ list }) => { - const operations = list - .map((item) => { - item.board.board.title = item.item.operationId; - item.board.board.description = item.item.description; - item.board.board.version = "0.0.3"; - - return { - [item.item.operationId]: item, - }; - }) - .reduce((acc, curr) => { - return { ...acc, ...curr }; - }, {}); - return { ...operations }; -}); - -export default await board(({ url, context, builderPath }) => { - url - .title("Open API URL") - .description( - "The URL of the Open API spec that you want to convert to a board." - ) - .isString(); - context - .title("Context") - .description( - "The query that will be used to generate any required data for the POST request" - ) - .isString(); - builderPath - .title("Path to the request builder") - .description( - "The path to the request builder that will be used to create the request body." - ) - .isString(); - - // Get the Open API spec from the given URL - const fetchOpenAPISpec = core - .fetch({ $id: "fetch_open_api_schema", url }) - .response.as("json"); - - const curriedSpecBoard = core.curry({ - $id: "curry", - $board: createSpecBoard, - context, - builderPath, - }); - - // Get the Open API spec from the given URL. - return fetchOpenAPISpec - .to(validateIsOpenAPI({ $id: "validateIsOpenAPI" })) - .as("json") - .to(generateAPISpecs({ $id: "generateAPISpecs", context, builderPath })) - .as("list") - .to( - core.map({ - $id: "createFetchBoards", - board: curriedSpecBoard, - }) - ) - .to(convertBoardListToObject({ $id: "convertBoardListToObject" })); -}).serialize(metaData); diff --git a/boards/tools/openapi/openapi.json b/boards/tools/openapi/openapi.json deleted file mode 100644 index 90e416810a9..00000000000 --- a/boards/tools/openapi/openapi.json +++ /dev/null @@ -1,512 +0,0 @@ -{ - "title": "Create a board from an Open API spec", - "description": "Converts an Open API spec to a board.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.3", - "edges": [ - { - "from": "convertBoardListToObject", - "to": "output-2", - "out": "*", - "in": "" - }, - { - "from": "createFetchBoards", - "to": "convertBoardListToObject", - "out": "*", - "in": "" - }, - { - "from": "curry", - "to": "createFetchBoards", - "out": "board", - "in": "board" - }, - { - "from": "generateAPISpecs", - "to": "createFetchBoards", - "out": "list", - "in": "list" - }, - { - "from": "input-1", - "to": "fetch_open_api_schema", - "out": "url", - "in": "url" - }, - { - "from": "input-1", - "to": "curry", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "curry", - "out": "builderPath", - "in": "builderPath" - }, - { - "from": "input-1", - "to": "generateAPISpecs", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "generateAPISpecs", - "out": "builderPath", - "in": "builderPath" - }, - { - "from": "validateIsOpenAPI", - "to": "generateAPISpecs", - "out": "json", - "in": "json" - }, - { - "from": "fetch_open_api_schema", - "to": "validateIsOpenAPI", - "out": "response", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": {} - }, - { - "id": "convertBoardListToObject", - "type": "runJavascript", - "configuration": { - "code": "const convertBoardListToObject = ({ list }) => {\n const operations = list\n .map((item) => {\n item.board.board.title = item.item.operationId;\n item.board.board.description = item.item.description;\n item.board.board.version = \"0.0.3\";\n\n return {\n [item.item.operationId]: item,\n };\n })\n .reduce((acc, curr) => {\n return { ...acc, ...curr };\n }, {});\n return { ...operations };\n};", - "name": "convertBoardListToObject", - "raw": true - } - }, - { - "id": "createFetchBoards", - "type": "map", - "configuration": {} - }, - { - "id": "curry", - "type": "curry", - "configuration": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "input-1", - "to": "createBoardInputs", - "out": "item", - "in": "item" - }, - { - "from": "input-1", - "to": "output-3", - "out": "item", - "in": "item" - }, - { - "from": "input-1", - "to": "lambda-5", - "out": "item", - "in": "item" - }, - { - "from": "input-1", - "to": "lambda-5", - "out": "builderPath", - "in": "builderPath" - }, - { - "from": "input-1", - "to": "lambda-5", - "out": "item", - "in": "item" - }, - { - "from": "createBoardInputs", - "to": "output-3", - "out": "*", - "in": "" - }, - { - "from": "createBoardInputs", - "to": "lambda-5", - "out": "*", - "in": "" - }, - { - "from": "lambda-5", - "to": "output-3", - "out": "board", - "in": "board" - } - ], - "nodes": [ - { - "id": "output-3", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": "string", - "title": "item" - }, - "board": { - "type": "string", - "title": "board" - } - } - } - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": "string", - "title": "item" - }, - "builderPath": { - "type": "string", - "title": "builderPath" - } - }, - "required": [ - "item", - "builderPath" - ] - } - } - }, - { - "id": "createBoardInputs", - "type": "runJavascript", - "configuration": { - "code": "const createBoardInputs = ({ item }) => {\n const { parameters } = item;\n const nodes = [];\n\n const inputNode = {\n id: `input`,\n type: `input`,\n configuration: {\n schema: {\n type: \"object\",\n properties: parameters.reduce((params, param) => {\n const schema = { ...param.schema };\n schema.title = param.name;\n schema.description = param.description || param.schema.title;\n\n if (param.required) {\n if (\"default\" in param == false) {\n schema.default = undefined;\n } else {\n schema.default = param.default;\n }\n } else {\n schema.default = param.default || null;\n }\n\n if (param.in == \"query\" || param.in == \"path\") {\n params[param.name] = schema;\n }\n\n return params;\n }, {}),\n },\n },\n };\n\n nodes.push(inputNode);\n\n nodes.push({ id: \"output\", type: \"output\" });\n\n const edges = parameters.map((param) => {\n return {\n from: `input`,\n out: param.name,\n to: \"output\",\n in: param.name,\n optional: !param.required,\n };\n });\n\n if (\"secrets\" in item && item.secrets != undefined) {\n const apiKeyName = `${item.info.title\n .replace(/[^a-zA-Z0-9]+/g, \"_\")\n .toUpperCase()}_KEY`;\n\n nodes.push({\n id: \"input-secrets\",\n type: \"secrets\",\n configuration: {\n keys: [apiKeyName],\n },\n });\n\n edges.push({\n from: \"input-secrets\",\n out: apiKeyName,\n to: \"output\",\n in: apiKeyName,\n });\n }\n\n if (nodes.length == 0) {\n nodes.push({ id: \"input\", type: \"input\" });\n }\n\n if (edges.length == 0) {\n edges.push({ from: `input`, out: \"*\", to: \"output\", in: \"\" });\n }\n\n const graph = {\n title: `API Inputs for ${item.operationId}`,\n url: \"#\",\n nodes,\n edges,\n };\n\n return { graph };\n };", - "name": "createBoardInputs", - "raw": true - } - }, - { - "id": "lambda-5", - "type": "lambda", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "fetch-6", - "to": "output-5", - "out": "response", - "in": "api_json_response" - }, - { - "from": "createFetchParameters", - "to": "fetch-6", - "out": "*", - "in": "" - }, - { - "from": "input-1", - "to": "getBuilderPath", - "out": "item", - "in": "item" - }, - { - "from": "input-1", - "to": "createRequestBody", - "out": "input", - "in": "input" - }, - { - "from": "input-1", - "to": "mergeInputs", - "out": "item", - "in": "item" - }, - { - "from": "input-1", - "to": "mergeInputs", - "out": "graph", - "in": "graph" - }, - { - "from": "input-1", - "to": "toAPIInputs", - "out": "item", - "in": "item" - }, - { - "from": "input-1", - "to": "createFetchParameters", - "out": "item", - "in": "item" - }, - { - "from": "toAPIInputs", - "to": "createFetchParameters", - "out": "api_inputs", - "in": "api_inputs" - }, - { - "from": "getBuilderPath", - "to": "generateRequestBodyFromSchema", - "out": "*", - "in": "" - }, - { - "from": "createRequestBody", - "to": "toAPIInputs", - "out": "requestBody", - "in": "requestBody" - }, - { - "from": "mergeInputs", - "to": "lambda-4", - "out": "*", - "in": "" - }, - { - "from": "lambda-4", - "to": "toAPIInputs", - "out": "*", - "in": "" - }, - { - "from": "lambda-4", - "to": "toAPIInputs", - "out": "board", - "in": "$board" - }, - { - "from": "generateRequestBodyFromSchema", - "to": "createRequestBody", - "out": "text", - "in": "text" - } - ], - "nodes": [ - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "api_json_response": { - "title": "response", - "description": "The response from the fetch request", - "type": [ - "string", - "object" - ] - } - } - } - } - }, - { - "id": "fetch-6", - "type": "fetch", - "configuration": {} - }, - { - "id": "createFetchParameters", - "type": "runJavascript", - "configuration": { - "code": "const createFetchParameters = ({ item, api_inputs }) => {\n const { method, parameters, secrets, requestBody } = item;\n debugger;\n console.log(\"API Inputs\", item);\n\n let { url } = item;\n\n const queryStringParameters = {};\n\n if (typeof api_inputs == \"string\") {\n api_inputs = JSON.parse(api_inputs);\n }\n\n if (\n parameters != undefined &&\n parameters.length > 0 &&\n api_inputs == undefined\n ) {\n throw new Error(\n `Missing input for parameters ${JSON.stringify(parameters)}`\n );\n }\n\n for (const param of parameters) {\n if (api_inputs && param.name in api_inputs == false && param.required) {\n throw new Error(`Missing required parameter ${param.name}`);\n }\n\n if (api_inputs && param.name in api_inputs == false) {\n // Parameter is not required and not in input, so we can skip it.\n continue;\n }\n\n if (param.in == \"path\") {\n // Replace the path parameter with the value from the input.\n url = url.replace(`{${param.name}}`, api_inputs[param.name]);\n }\n\n if (param.in == \"query\") {\n queryStringParameters[param.name] = api_inputs[param.name];\n }\n }\n\n // If the method is POST or PUT, then we need to add the requestBody to the body.\n\n // We are going to want to add in the secret somehow\n const headers = {};\n\n // Create the query string\n const queryString = Object.entries(queryStringParameters)\n .map(([key, value]) => {\n return `${key}=${value}`;\n })\n .join(\"&\");\n\n if (queryString.length > 0) {\n url = `${url}?${queryString}`;\n }\n\n // Many APIs will require an authentication token but they don't define it in the Open API spec.\n if (secrets != undefined && secrets[1].scheme == \"bearer\") {\n const envKey = `${item.info.title\n .replace(/[^a-zA-Z0-9]+/g, \"_\")\n .toUpperCase()}_KEY`;\n const envValue = api_inputs[envKey];\n\n headers[\"Authorization\"] = `Bearer ${envValue}`;\n }\n\n let body = undefined;\n\n if (requestBody) {\n // We know the method needs a request Body.\n // Find the first input that matches the valid required schema of the API.\n let requestContentType;\n\n // We can only handle JSON\n if (\"requestBody\" in api_inputs) {\n body =\n typeof api_inputs[\"requestBody\"] == \"string\"\n ? JSON.parse(api_inputs[\"requestBody\"])\n : api_inputs[\"requestBody\"];\n requestContentType = \"application/json\";\n }\n\n if (body == undefined) {\n throw new Error(\n `Missing required request body for ${JSON.stringify(requestBody)}`\n );\n }\n\n headers[\"Content-Type\"] = requestContentType;\n }\n return { url, method, headers, body, queryString };\n };", - "name": "createFetchParameters", - "raw": true - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": "string", - "title": "item" - }, - "graph": { - "type": "string", - "title": "graph" - }, - "input": { - "type": "string", - "title": "input" - } - }, - "required": [ - "item", - "graph" - ] - } - } - }, - { - "id": "toAPIInputs", - "type": "invoke", - "configuration": {} - }, - { - "id": "getBuilderPath", - "type": "runJavascript", - "configuration": { - "code": "const getBuilderPath = ({ item }) => {\n return {\n path: item.builderPath,\n $board: item.builderPath,\n context: item.context,\n text: item.context,\n theSchema: item.requestBody[\"application/json\"].schema,\n };\n };", - "name": "getBuilderPath", - "raw": true - } - }, - { - "id": "createRequestBody", - "type": "runJavascript", - "configuration": { - "code": "const createRequestBody = ({ text, input }) => {\n debugger;\n return { requestBody: text, input };\n };", - "name": "createRequestBody", - "raw": true - } - }, - { - "id": "mergeInputs", - "type": "invoke", - "configuration": {} - }, - { - "id": "lambda-4", - "type": "lambda", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3", - "out": "*" - }, - { - "from": "fn-3", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3", - "type": "runJavascript", - "configuration": { - "code": "const fn_3 = (item) => {\n debugger;\n console.log(\"API Inputs\", item);\n return { api_inputs: item };\n };", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - { - "id": "generateRequestBodyFromSchema", - "type": "invoke", - "configuration": {} - } - ], - "graphs": {} - } - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "generateAPISpecs", - "type": "runJavascript", - "configuration": { - "code": "const generateAPISpecs = ({ json, context, builderPath }) => {\n const { paths, info } = json;\n const baseUrl = json.servers[0].url;\n\n /*\n If there is no operation ID, we need to generate one from the path, but format it like a JS function name.\n */\n const inferOperationId = (path, method) => {\n let newName = path\n .split(\"/\")\n .map((part) =>\n part.length == 0 ? part : part[0].toUpperCase() + part.slice(1)\n )\n .join(\"\")\n .replace(/[.-]/g, \"\") // Remove dashes and dots\n .replace(/[{}]/g, \"\"); // Remove curly braces (need to improve this)\n\n return `${method}${newName}`;\n };\n\n const apis = Object.entries(paths)\n .map(([key, value]) => {\n // Parse parameters on the path\n let pathParameters = [];\n if (\"parameters\" in value) {\n pathParameters = value.parameters.map((param) => {\n // We can only manage reference objects for now.\n if (\"$ref\" in param) {\n if (param.$ref.startsWith(\"#\") == false) {\n return undefined;\n }\n\n const pathParts = param.$ref.replace(/^#\\//, \"\").split(\"/\");\n let obj = json;\n\n for (const part of pathParts) {\n obj = obj[part];\n }\n\n return obj;\n } else {\n return param;\n }\n });\n }\n\n return Object.keys(value)\n .filter((method) => [\"post\", \"get\"].includes(method))\n .map((method) => {\n // Operation ID might not exist.\n const operationId =\n value[method].operationId ||\n inferOperationId(key, method, value[method]);\n\n const data = value[method];\n\n // All parameters, path or query are held in the parameters array ( but might be a reference)\n const parameters =\n \"parameters\" in data == false\n ? []\n : data.parameters.map((param) => {\n // We can only manage reference objects for now.\n if (\"$ref\" in param) {\n if (param.$ref.startsWith(\"#\") == false) {\n return undefined;\n }\n\n const pathParts = param.$ref.replace(/^#\\//, \"\").split(\"/\");\n let obj = json;\n\n for (const part of pathParts) {\n obj = obj[part];\n }\n\n return obj;\n } else {\n return param;\n }\n });\n\n parameters.push(...pathParameters);\n\n const requestBody =\n \"requestBody\" in data == false\n ? undefined\n : Object.entries(data.requestBody.content)\n .map(([contentType, reqeustParams]) => {\n // We can only manage reference objects for now.\n if (\"$ref\" in reqeustParams.schema) {\n if (reqeustParams.schema.$ref.startsWith(\"#\") == false) {\n return undefined;\n }\n\n const pathParts = reqeustParams.schema.$ref\n .replace(/^#\\//, \"\")\n .split(\"/\");\n let obj = json;\n\n for (const part of pathParts) {\n obj = obj[part];\n }\n\n if (\"description\" in obj == false) {\n obj.description = `Request POST data (format: ${contentType})`;\n }\n return { [contentType]: { schema: obj } };\n }\n return { [contentType]: reqeustParams };\n })\n .reduce((acc, curr) => {\n return { ...acc, ...curr };\n }, {});\n\n // We will need to hook up `secrets` to this somehow.\n let secrets = undefined;\n // We can only support Bearer tokens for now.\n if (\"components\" in json && \"securitySchemes\" in json.components) {\n // Check to see if global security is defined, it's the same type and && it is a bearer token.\n const bearerSecurity = Object.entries(\n json.components.securitySchemes\n ).find(([securityMethodKey, securityValue]) => {\n const security = json.security.find((item) => {\n return securityMethodKey in item;\n });\n\n return (\n security &&\n securityValue.type == \"http\" &&\n securityValue.scheme == \"bearer\"\n );\n });\n\n if (bearerSecurity != undefined) {\n secrets = bearerSecurity;\n }\n }\n\n const headers = {\n operationId,\n url: baseUrl.replace(/\\/$/, \"\") + key,\n method: method.toUpperCase(),\n description: data.description,\n summary: data.summary,\n parameters,\n requestBody,\n secrets,\n info,\n context,\n builderPath,\n };\n\n return headers;\n })\n .flat();\n })\n .flat();\n\n return { list: apis };\n};", - "name": "generateAPISpecs", - "raw": true - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "url": { - "title": "Open API URL", - "description": "The URL of the Open API spec that you want to convert to a board.", - "type": "string" - }, - "context": { - "title": "Context", - "description": "The query that will be used to generate any required data for the POST request", - "type": "string" - }, - "builderPath": { - "title": "Path to the request builder", - "description": "The path to the request builder that will be used to create the request body.", - "type": "string" - } - }, - "required": [ - "url", - "context", - "builderPath" - ] - } - } - }, - { - "id": "validateIsOpenAPI", - "type": "runJavascript", - "configuration": { - "code": "const validateIsOpenAPI = ({ json }) => {\n if (\"openapi\" in json == false) {\n throw new Error(\"Not an Open API spec.\");\n }\n\n if (\"servers\" in json == false) {\n throw new Error(\"No servers in Open API spec.\");\n }\n\n if (\"paths\" in json == false) {\n throw new Error(\"No paths in Open API spec.\");\n }\n\n return { json };\n};", - "name": "validateIsOpenAPI", - "raw": true - } - }, - { - "id": "fetch_open_api_schema", - "type": "fetch", - "configuration": {} - } - ], - "kits": [], - "graphs": {} -} \ No newline at end of file diff --git a/boards/tools/openapi/request-builder.json b/boards/tools/openapi/request-builder.json deleted file mode 100644 index 747193f3efa..00000000000 --- a/boards/tools/openapi/request-builder.json +++ /dev/null @@ -1,217 +0,0 @@ -{ - "title": "Request Body Builder", - "description": "Builds the POST body for a request", - "version": "0.0.1", - "nodes": [ - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "json": { - "type": "string", - "title": "json", - "examples": [] - } - }, - "required": [] - } - }, - "metadata": { - "visual": { - "x": 615, - "y": 110 - } - } - }, - { - "id": "text-2daa1e8a", - "type": "text", - "metadata": { - "visual": { - "x": 142, - "y": -695 - } - }, - "configuration": { - "model": "gemini-1.5-pro-latest" - } - }, - { - "id": "validateJson-eefab6f5", - "type": "validateJson", - "metadata": { - "visual": { - "x": 248, - "y": -102 - } - } - }, - { - "id": "promptTemplate-47d4a7bf", - "type": "promptTemplate", - "metadata": { - "visual": { - "x": -228, - "y": -588.9999999999999 - } - }, - "configuration": { - "template": "Consider the following JSON schema: \n\n```\n{{schema}}\n```\n\nThis JSON Schema represents the format I want you to follow to generate your answer.\n\nBased on all this information, generate a valid JSON object containing the information I requested.\n\nIf you don't have enough information and their isn't a default value, ask for it", - "schema": "{ \"type\": \"object\", \"additionalProperties\": false, \"properties\": { \"input\": { \"description\": \"Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or array of token arrays. The input must not exceed the max input tokens for the model (8192 tokens for `text-embedding-ada-002`), cannot be an empty string, and any array must be 2048 dimensions or less. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens.\\n\", \"example\": \"The quick brown fox jumped over the lazy dog\", \"oneOf\": [ { \"type\": \"string\", \"title\": \"string\", \"description\": \"The string that will be turned into an embedding.\", \"default\": \"\", \"example\": \"This is a test.\" }, { \"type\": \"array\", \"title\": \"array\", \"description\": \"The array of strings that will be turned into an embedding.\", \"minItems\": 1, \"maxItems\": 2048, \"items\": { \"type\": \"string\", \"default\": \"\", \"example\": \"['This is a test.']\" } }, { \"type\": \"array\", \"title\": \"array\", \"description\": \"The array of integers that will be turned into an embedding.\", \"minItems\": 1, \"maxItems\": 2048, \"items\": { \"type\": \"integer\" }, \"example\": \"[1212, 318, 257, 1332, 13]\" }, { \"type\": \"array\", \"title\": \"array\", \"description\": \"The array of arrays containing integers that will be turned into an embedding.\", \"minItems\": 1, \"maxItems\": 2048, \"items\": { \"type\": \"array\", \"minItems\": 1, \"items\": { \"type\": \"integer\" } }, \"example\": \"[[1212, 318, 257, 1332, 13]]\" } ], \"x-oaiExpandable\": true }, \"model\": { \"description\": \"ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them.\\n\", \"example\": \"text-embedding-3-small\", \"anyOf\": [ { \"type\": \"string\" }, { \"type\": \"string\", \"enum\": [ \"text-embedding-ada-002\", \"text-embedding-3-small\", \"text-embedding-3-large\" ] } ], \"x-oaiTypeLabel\": \"string\" }, \"encoding_format\": { \"description\": \"The format to return the embeddings in. Can be either `float` or [`base64`](https://pypi.org/project/pybase64/).\", \"example\": \"float\", \"default\": \"float\", \"type\": \"string\", \"enum\": [\"float\", \"base64\"] }, \"dimensions\": { \"description\": \"The number of dimensions the resulting output embeddings should have. Only supported in `text-embedding-3` and later models.\\n\", \"type\": \"integer\", \"minimum\": 1 }, \"user\": { \"type\": \"string\", \"example\": \"user-1234\", \"description\": \"A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\\n\" } }, \"required\": [\"model\", \"input\"] }" - } - }, - { - "id": "input-a15bcc81", - "type": "input", - "metadata": { - "visual": { - "x": -200, - "y": -342 - }, - "title": "prompt-input", - "logLevel": "debug" - } - }, - { - "id": "input-f44b216d", - "type": "input", - "metadata": { - "visual": { - "x": -523, - "y": -234 - } - }, - "configuration": { - "schema": { - "properties": { - "theSchema": { - "type": "string", - "title": "The Schema", - "examples": [] - } - }, - "required": [], - "type": "object" - } - } - }, - { - "id": "runJavascript-b70ca9b3", - "type": "runJavascript", - "metadata": { - "visual": { - "x": 426, - "y": -642 - } - }, - "configuration": { - "name": "run", - "code": "function run(args) {\n console.log(args)\n if (\"$error\" in args) {\n \n return { \n //\"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"additional\": {\n \"type\": \"string\",\n \"title\": \"Additional Data\",\n \"description\": args.$error.inputs.json || args.$error.error.message,\n \"examples\": []\n }\n },\n \"required\": []\n }\n // }\n }\n return;\n}" - } - }, - { - "id": "input-9dfbdaed", - "type": "input", - "metadata": { - "visual": { - "x": 490, - "y": -346.9999999999999 - }, - "title": "additional-data-input", - "logLevel": "debug" - } - }, - { - "id": "promptTemplate-df5c15c1", - "type": "promptTemplate", - "configuration": { - "template": "{{text}}\n\nThe following data will override conflicting statements\n\n{{additional}}" - }, - "metadata": { - "visual": { - "x": 703, - "y": -191 - } - } - } - ], - "edges": [ - { - "from": "text-2daa1e8a", - "to": "validateJson-eefab6f5", - "out": "text", - "in": "json" - }, - { - "from": "validateJson-eefab6f5", - "to": "output", - "out": "json", - "in": "text" - }, - { - "from": "input-a15bcc81", - "to": "text-2daa1e8a", - "out": "text", - "in": "text" - }, - { - "from": "input-f44b216d", - "to": "promptTemplate-47d4a7bf", - "out": "theSchema", - "in": "schema" - }, - { - "from": "validateJson-eefab6f5", - "to": "runJavascript-b70ca9b3", - "out": "$error", - "in": "$error" - }, - { - "from": "input-a15bcc81", - "to": "runJavascript-b70ca9b3", - "out": "text", - "in": "text" - }, - { - "from": "runJavascript-b70ca9b3", - "to": "input-9dfbdaed", - "out": "result", - "in": "schema" - }, - { - "from": "input-a15bcc81", - "to": "promptTemplate-df5c15c1", - "out": "text", - "in": "text" - }, - { - "from": "input-9dfbdaed", - "to": "promptTemplate-df5c15c1", - "out": "additional", - "in": "additional" - }, - { - "from": "promptTemplate-df5c15c1", - "to": "text-2daa1e8a", - "out": "prompt", - "in": "text" - }, - { - "from": "promptTemplate-47d4a7bf", - "to": "text-2daa1e8a", - "out": "prompt", - "in": "systemInstruction", - "constant": true - }, - { - "from": "input-f44b216d", - "to": "validateJson-eefab6f5", - "out": "theSchema", - "in": "schema", - "constant": true - } - ] -} diff --git a/boards/tools/openapi/tests/README.md b/boards/tools/openapi/tests/README.md deleted file mode 100644 index e32ad8f8f14..00000000000 --- a/boards/tools/openapi/tests/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Tests for the OpenAPI Board - -## Running the Board - -```bash -breadboard run boards/tools/openapi/tests/index.js --kit @google-labs/llm-starter --kit @google-labs/core-kit -i "{\"url\":\"https://api.apis.guru/v2/specs/apis.guru/2.2.0/openapi.json\"}" -``` - -### XKCD API test - -```bash -breadboard run boards/tools/openapi/tests/xkcd.js --kit @google-labs/llm-starter --kit @google-labs/core-kit -i "{\"url\":\"https://api.apis.guru/v2/specs/xkcd.com/1.0.0/openapi.json\"}" -``` - -### Inputs - -- url - The url to the OpenAPI spec (JSON only for now) diff --git a/boards/tools/openapi/tests/index.js b/boards/tools/openapi/tests/index.js deleted file mode 100644 index f05dadd427d..00000000000 --- a/boards/tools/openapi/tests/index.js +++ /dev/null @@ -1,25 +0,0 @@ -import { base, board, code } from "@google-labs/breadboard"; -import { core } from "@google-labs/core-kit"; - -// To run this: npx breadboard run boards/tools/openapi/tests/index.js --kit @google-labs/llm-starter --kit @google-labs/core-kit -i "{\"url\":\"https://api.apis.guru/v2/specs/apis.guru/2.2.0/openapi.json\"}" - -const metaData = { - title: "Create a board from an Open API spec", - description: "Converts an Open API spec to a board.", - version: "0.0.3", -}; - -export default await board(() => { - const input = base.input({ $id: "input" }); - - const apiBoard = core.invoke({ path: "../index.json", url: input.url }); - - // This tests the input parameters - return core.invoke().in({ - board: apiBoard.getAPI, - input: { - provider: "apis.guru", - api: "2.2.0", - }, - }); -}).serialize(metaData); diff --git a/boards/tools/openapi/tests/index.json b/boards/tools/openapi/tests/index.json deleted file mode 100644 index 61607f4268a..00000000000 --- a/boards/tools/openapi/tests/index.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "title": "Create a board from an Open API spec", - "description": "Converts an Open API spec to a board.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.1.0/packages/schema/breadboard.schema.json", - "version": "0.0.3", - "edges": [ - { - "from": "invoke-4", - "to": "output-2", - "out": "*", - "in": "" - }, - { - "from": "invoke-3", - "to": "invoke-4", - "out": "getAPI", - "in": "board" - }, - { - "from": "input", - "to": "invoke-3", - "out": "url", - "in": "url" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": {} - }, - { - "id": "invoke-4", - "type": "invoke", - "configuration": { - "input": { - "provider": "apis.guru", - "api": "2.2.0" - } - } - }, - { - "id": "invoke-3", - "type": "invoke", - "configuration": { - "path": "../index.json" - } - }, - { - "id": "input", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "url": { - "type": "string", - "title": "url" - } - }, - "required": [ - "url" - ] - } - } - } - ], - "kits": [], - "graphs": {} -} \ No newline at end of file diff --git a/boards/tools/openapi/tests/openai.js b/boards/tools/openapi/tests/openai.js deleted file mode 100644 index 9cdb8a0d273..00000000000 --- a/boards/tools/openapi/tests/openai.js +++ /dev/null @@ -1,32 +0,0 @@ -import { base, board, code } from "@google-labs/breadboard"; -import { core } from "@google-labs/core-kit"; - -// To run this: npx breadboard run boards/tools/openapi/tests/openai.js --kit @google-labs/core-kit -i "{\"url\":\"https://raw.githubusercontent.com/breadboard-ai/breadboard/c371c2cd5aca33673e30fc647c920228752e41ee/recipes/tools/openapi/tests/specs/openai.json\"}" - -// YAML Open AI - https://raw.githubusercontent.com/openai/openai-openapi/master/openapi.yaml => https://raw.githubusercontent.com/breadboard-ai/breadboard/c371c2cd5aca33673e30fc647c920228752e41ee/recipes/tools/openapi/tests/specs/openai.json - -const metaData = { - title: "Create a board from an Open API spec", - description: "Converts an Open API spec to a board.", - version: "0.0.3", -}; - -export default await board(() => { - const input = base.input({ $id: "input" }); - - const apiBoard = core.invoke({ path: "../index.json", url: input.url }); - - // This tests the input parameters - return core.invoke().in({ - board: apiBoard.createEmbedding, - api_inputs: { - bearer: "OPENAI_API_KEY", - "application/json": { - input: - "Hello, my name is Paul and I'm not a large language model. I'm a real boy.", - model: "text-embedding-ada-002", - }, - }, - ...core.secrets({ keys: ["OPENAI_API_KEY"] }), - }); -}).serialize(metaData); diff --git a/boards/tools/openapi/tests/openai.json b/boards/tools/openapi/tests/openai.json deleted file mode 100644 index c277578eaef..00000000000 --- a/boards/tools/openapi/tests/openai.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "title": "Create a board from an Open API spec", - "description": "Converts an Open API spec to a board.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.1.0/packages/schema/breadboard.schema.json", - "version": "0.0.3", - "edges": [ - { - "from": "invoke-4", - "to": "output-2", - "out": "*", - "in": "" - }, - { - "from": "invoke-3", - "to": "invoke-4", - "out": "createEmbedding", - "in": "board" - }, - { - "from": "secrets-5", - "to": "invoke-4", - "out": "*", - "in": "" - }, - { - "from": "input", - "to": "invoke-3", - "out": "url", - "in": "url" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": {} - }, - { - "id": "invoke-4", - "type": "invoke", - "configuration": { - "api_inputs": { - "bearer": "OPENAI_API_KEY", - "application/json": { - "input": "Hello, my name is Paul and I'm not a large language model. I'm a real boy.", - "model": "text-embedding-ada-002" - } - } - } - }, - { - "id": "invoke-3", - "type": "invoke", - "configuration": { - "path": "../index.json" - } - }, - { - "id": "secrets-5", - "type": "secrets", - "configuration": { - "keys": [ - "OPENAI_API_KEY" - ] - } - }, - { - "id": "input", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "url": { - "type": "string", - "title": "url" - } - }, - "required": [ - "url" - ] - } - } - } - ], - "kits": [], - "graphs": {} -} \ No newline at end of file diff --git a/boards/tools/openapi/tests/specs/openai.json b/boards/tools/openapi/tests/specs/openai.json deleted file mode 100644 index e84ad2645a9..00000000000 --- a/boards/tools/openapi/tests/specs/openai.json +++ /dev/null @@ -1,8849 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "OpenAI API", - "description": "The OpenAI REST API. Please see https://platform.openai.com/docs/api-reference for more details.", - "version": "2.0.0", - "termsOfService": "https://openai.com/policies/terms-of-use", - "contact": { - "name": "OpenAI Support", - "url": "https://help.openai.com/" - }, - "license": { - "name": "MIT", - "url": "https://github.com/openai/openai-openapi/blob/master/LICENSE" - } - }, - "servers": [ - { - "url": "https://api.openai.com/v1" - } - ], - "tags": [ - { - "name": "Assistants", - "description": "Build Assistants that can call models and use tools." - }, - { - "name": "Audio", - "description": "Learn how to turn audio into text or text into audio." - }, - { - "name": "Chat", - "description": "Given a list of messages comprising a conversation, the model will return a response." - }, - { - "name": "Completions", - "description": "Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position." - }, - { - "name": "Embeddings", - "description": "Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms." - }, - { - "name": "Fine-tuning", - "description": "Manage fine-tuning jobs to tailor a model to your specific training data." - }, - { - "name": "Files", - "description": "Files are used to upload documents that can be used with features like Assistants and Fine-tuning." - }, - { - "name": "Images", - "description": "Given a prompt and/or an input image, the model will generate a new image." - }, - { - "name": "Models", - "description": "List and describe the various models available in the API." - }, - { - "name": "Moderations", - "description": "Given a input text, outputs if the model classifies it as violating OpenAI's content policy." - }, - { - "name": "Fine-tunes", - "description": "Manage legacy fine-tuning jobs to tailor a model to your specific training data." - }, - { - "name": "Edits", - "description": "Given a prompt and an instruction, the model will return an edited version of the prompt." - } - ], - "paths": { - "/chat/completions": { - "post": { - "operationId": "createChatCompletion", - "tags": [ - "Chat" - ], - "summary": "Creates a model response for the given chat conversation.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateChatCompletionRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateChatCompletionResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create chat completion", - "group": "chat", - "returns": "Returns a [chat completion](/docs/api-reference/chat/object) object, or a streamed sequence of [chat completion chunk](/docs/api-reference/chat/streaming) objects if the request is streamed.\n", - "path": "create", - "examples": [ - { - "title": "Default", - "request": { - "curl": "curl https://api.openai.com/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"model\": \"VAR_model_id\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a helpful assistant.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Hello!\"\n }\n ]\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\ncompletion = client.chat.completions.create(\n model=\"VAR_model_id\",\n messages=[\n {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n {\"role\": \"user\", \"content\": \"Hello!\"}\n ]\n)\n\nprint(completion.choices[0].message)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const completion = await openai.chat.completions.create({\n messages: [{ role: \"system\", content: \"You are a helpful assistant.\" }],\n model: \"VAR_model_id\",\n });\n\n console.log(completion.choices[0]);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion\",\n \"created\": 1677652288,\n \"model\": \"gpt-3.5-turbo-0613\",\n \"system_fingerprint\": \"fp_44709d6fcb\",\n \"choices\": [{\n \"index\": 0,\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"\\n\\nHello there, how may I assist you today?\",\n },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }],\n \"usage\": {\n \"prompt_tokens\": 9,\n \"completion_tokens\": 12,\n \"total_tokens\": 21\n }\n}\n" - }, - { - "title": "Image input", - "request": { - "curl": "curl https://api.openai.com/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"model\": \"gpt-4-vision-preview\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": \"What’s in this image?\"\n },\n {\n \"type\": \"image_url\",\n \"image_url\": {\n \"url\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg\"\n }\n }\n ]\n }\n ],\n \"max_tokens\": 300\n }'\n", - "python": "from openai import OpenAI\n\nclient = OpenAI()\n\nresponse = client.chat.completions.create(\n model=\"gpt-4-vision-preview\",\n messages=[\n {\n \"role\": \"user\",\n \"content\": [\n {\"type\": \"text\", \"text\": \"What’s in this image?\"},\n {\n \"type\": \"image_url\",\n \"image_url\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg\",\n },\n ],\n }\n ],\n max_tokens=300,\n)\n\nprint(response.choices[0])\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const response = await openai.chat.completions.create({\n model: \"gpt-4-vision-preview\",\n messages: [\n {\n role: \"user\",\n content: [\n { type: \"text\", text: \"What’s in this image?\" },\n {\n type: \"image_url\",\n image_url:\n \"https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg\",\n },\n ],\n },\n ],\n });\n console.log(response.choices[0]);\n}\nmain();" - }, - "response": "{\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion\",\n \"created\": 1677652288,\n \"model\": \"gpt-3.5-turbo-0613\",\n \"system_fingerprint\": \"fp_44709d6fcb\",\n \"choices\": [{\n \"index\": 0,\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"\\n\\nHello there, how may I assist you today?\",\n },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }],\n \"usage\": {\n \"prompt_tokens\": 9,\n \"completion_tokens\": 12,\n \"total_tokens\": 21\n }\n}\n" - }, - { - "title": "Streaming", - "request": { - "curl": "curl https://api.openai.com/v1/chat/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"model\": \"VAR_model_id\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a helpful assistant.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Hello!\"\n }\n ],\n \"stream\": true\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\ncompletion = client.chat.completions.create(\n model=\"VAR_model_id\",\n messages=[\n {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n {\"role\": \"user\", \"content\": \"Hello!\"}\n ],\n stream=True\n)\n\nfor chunk in completion:\n print(chunk.choices[0].delta)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const completion = await openai.chat.completions.create({\n model: \"VAR_model_id\",\n messages: [\n {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n {\"role\": \"user\", \"content\": \"Hello!\"}\n ],\n stream: true,\n });\n\n for await (const chunk of completion) {\n console.log(chunk.choices[0].delta.content);\n }\n}\n\nmain();" - }, - "response": "{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"logprobs\":null,\"finish_reason\":null}]}\n\n{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{\"content\":\"Hello\"},\"logprobs\":null,\"finish_reason\":null}]}\n\n{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{\"content\":\"!\"},\"logprobs\":null,\"finish_reason\":null}]}\n\n....\n\n{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{\"content\":\" today\"},\"logprobs\":null,\"finish_reason\":null}]}\n\n{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{\"content\":\"?\"},\"logprobs\":null,\"finish_reason\":null}]}\n\n{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{},\"logprobs\":null,\"finish_reason\":\"stop\"}]}\n" - }, - { - "title": "Functions", - "request": { - "curl": "curl https://api.openai.com/v1/chat/completions \\\n-H \"Content-Type: application/json\" \\\n-H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n-d '{\n \"model\": \"gpt-3.5-turbo\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"What is the weather like in Boston?\"\n }\n ],\n \"tools\": [\n {\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_current_weather\",\n \"description\": \"Get the current weather in a given location\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"location\": {\n \"type\": \"string\",\n \"description\": \"The city and state, e.g. San Francisco, CA\"\n },\n \"unit\": {\n \"type\": \"string\",\n \"enum\": [\"celsius\", \"fahrenheit\"]\n }\n },\n \"required\": [\"location\"]\n }\n }\n }\n ],\n \"tool_choice\": \"auto\"\n}'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\ntools = [\n {\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_current_weather\",\n \"description\": \"Get the current weather in a given location\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"location\": {\n \"type\": \"string\",\n \"description\": \"The city and state, e.g. San Francisco, CA\",\n },\n \"unit\": {\"type\": \"string\", \"enum\": [\"celsius\", \"fahrenheit\"]},\n },\n \"required\": [\"location\"],\n },\n }\n }\n]\nmessages = [{\"role\": \"user\", \"content\": \"What's the weather like in Boston today?\"}]\ncompletion = client.chat.completions.create(\n model=\"VAR_model_id\",\n messages=messages,\n tools=tools,\n tool_choice=\"auto\"\n)\n\nprint(completion)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const messages = [{\"role\": \"user\", \"content\": \"What's the weather like in Boston today?\"}];\n const tools = [\n {\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_current_weather\",\n \"description\": \"Get the current weather in a given location\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"location\": {\n \"type\": \"string\",\n \"description\": \"The city and state, e.g. San Francisco, CA\",\n },\n \"unit\": {\"type\": \"string\", \"enum\": [\"celsius\", \"fahrenheit\"]},\n },\n \"required\": [\"location\"],\n },\n }\n }\n ];\n\n const response = await openai.chat.completions.create({\n model: \"gpt-3.5-turbo\",\n messages: messages,\n tools: tools,\n tool_choice: \"auto\",\n });\n\n console.log(response);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"chatcmpl-abc123\",\n \"object\": \"chat.completion\",\n \"created\": 1699896916,\n \"model\": \"gpt-3.5-turbo-0613\",\n \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": \"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n \"id\": \"call_abc123\",\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_current_weather\",\n \"arguments\": \"{\\n\\\"location\\\": \\\"Boston, MA\\\"\\n}\"\n }\n }\n ]\n },\n \"logprobs\": null,\n \"finish_reason\": \"tool_calls\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\": 82,\n \"completion_tokens\": 17,\n \"total_tokens\": 99\n }\n}\n" - } - ] - } - } - }, - "/completions": { - "post": { - "operationId": "createCompletion", - "tags": [ - "Completions" - ], - "summary": "Creates a completion for the provided prompt and parameters.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateCompletionRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateCompletionResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create completion", - "group": "completions", - "returns": "Returns a [completion](/docs/api-reference/completions/object) object, or a sequence of completion objects if the request is streamed.\n", - "legacy": true, - "examples": [ - { - "title": "No streaming", - "request": { - "curl": "curl https://api.openai.com/v1/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"model\": \"VAR_model_id\",\n \"prompt\": \"Say this is a test\",\n \"max_tokens\": 7,\n \"temperature\": 0\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.completions.create(\n model=\"VAR_model_id\",\n prompt=\"Say this is a test\",\n max_tokens=7,\n temperature=0\n)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const completion = await openai.completions.create({\n model: \"VAR_model_id\",\n prompt: \"Say this is a test.\",\n max_tokens: 7,\n temperature: 0,\n });\n\n console.log(completion);\n}\nmain();" - }, - "response": "{\n \"id\": \"cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7\",\n \"object\": \"text_completion\",\n \"created\": 1589478378,\n \"model\": \"VAR_model_id\",\n \"system_fingerprint\": \"fp_44709d6fcb\",\n \"choices\": [\n {\n \"text\": \"\\n\\nThis is indeed a test\",\n \"index\": 0,\n \"logprobs\": null,\n \"finish_reason\": \"length\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\": 5,\n \"completion_tokens\": 7,\n \"total_tokens\": 12\n }\n}\n" - }, - { - "title": "Streaming", - "request": { - "curl": "curl https://api.openai.com/v1/completions \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"model\": \"VAR_model_id\",\n \"prompt\": \"Say this is a test\",\n \"max_tokens\": 7,\n \"temperature\": 0,\n \"stream\": true\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nfor chunk in client.completions.create(\n model=\"VAR_model_id\",\n prompt=\"Say this is a test\",\n max_tokens=7,\n temperature=0,\n stream=True\n):\n print(chunk.choices[0].text)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const stream = await openai.completions.create({\n model: \"VAR_model_id\",\n prompt: \"Say this is a test.\",\n stream: true,\n });\n\n for await (const chunk of stream) {\n console.log(chunk.choices[0].text)\n }\n}\nmain();" - }, - "response": "{\n \"id\": \"cmpl-7iA7iJjj8V2zOkCGvWF2hAkDWBQZe\",\n \"object\": \"text_completion\",\n \"created\": 1690759702,\n \"choices\": [\n {\n \"text\": \"This\",\n \"index\": 0,\n \"logprobs\": null,\n \"finish_reason\": null\n }\n ],\n \"model\": \"gpt-3.5-turbo-instruct\"\n \"system_fingerprint\": \"fp_44709d6fcb\",\n}\n" - } - ] - } - } - }, - "/edits": { - "post": { - "operationId": "createEdit", - "deprecated": true, - "tags": [ - "Edits" - ], - "summary": "Creates a new edit for the provided input, instruction, and parameters.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateEditRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateEditResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create edit", - "returns": "Returns an [edit](/docs/api-reference/edits/object) object.\n", - "group": "edits", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/edits \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"model\": \"VAR_model_id\",\n \"input\": \"What day of the wek is it?\",\n \"instruction\": \"Fix the spelling mistakes\"\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.edits.create(\n model=\"VAR_model_id\",\n input=\"What day of the wek is it?\",\n instruction=\"Fix the spelling mistakes\"\n)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const edit = await openai.edits.create({\n model: \"VAR_model_id\",\n input: \"What day of the wek is it?\",\n instruction: \"Fix the spelling mistakes.\",\n });\n\n console.log(edit);\n}\n\nmain();" - }, - "response": "{\n \"object\": \"edit\",\n \"created\": 1589478378,\n \"choices\": [\n {\n \"text\": \"What day of the week is it?\",\n \"index\": 0,\n }\n ],\n \"usage\": {\n \"prompt_tokens\": 25,\n \"completion_tokens\": 32,\n \"total_tokens\": 57\n }\n}\n" - } - } - } - }, - "/images/generations": { - "post": { - "operationId": "createImage", - "tags": [ - "Images" - ], - "summary": "Creates an image given a prompt.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateImageRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImagesResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create image", - "group": "images", - "returns": "Returns a list of [image](/docs/api-reference/images/object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/images/generations \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"model\": \"dall-e-3\",\n \"prompt\": \"A cute baby sea otter\",\n \"n\": 1,\n \"size\": \"1024x1024\"\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.images.generate(\n model=\"dall-e-3\",\n prompt=\"A cute baby sea otter\",\n n=1,\n size=\"1024x1024\"\n)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const image = await openai.images.generate({ model: \"dall-e-3\", prompt: \"A cute baby sea otter\" });\n\n console.log(image.data);\n}\nmain();" - }, - "response": "{\n \"created\": 1589478378,\n \"data\": [\n {\n \"url\": \"https://...\"\n },\n {\n \"url\": \"https://...\"\n }\n ]\n}\n" - } - } - } - }, - "/images/edits": { - "post": { - "operationId": "createImageEdit", - "tags": [ - "Images" - ], - "summary": "Creates an edited or extended image given an original image and a prompt.", - "requestBody": { - "required": true, - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/CreateImageEditRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImagesResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create image edit", - "group": "images", - "returns": "Returns a list of [image](/docs/api-reference/images/object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/images/edits \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -F image=\"@otter.png\" \\\n -F mask=\"@mask.png\" \\\n -F prompt=\"A cute baby sea otter wearing a beret\" \\\n -F n=2 \\\n -F size=\"1024x1024\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.images.edit(\n image=open(\"otter.png\", \"rb\"),\n mask=open(\"mask.png\", \"rb\"),\n prompt=\"A cute baby sea otter wearing a beret\",\n n=2,\n size=\"1024x1024\"\n)\n", - "node.js": "import fs from \"fs\";\nimport OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const image = await openai.images.edit({\n image: fs.createReadStream(\"otter.png\"),\n mask: fs.createReadStream(\"mask.png\"),\n prompt: \"A cute baby sea otter wearing a beret\",\n });\n\n console.log(image.data);\n}\nmain();" - }, - "response": "{\n \"created\": 1589478378,\n \"data\": [\n {\n \"url\": \"https://...\"\n },\n {\n \"url\": \"https://...\"\n }\n ]\n}\n" - } - } - } - }, - "/images/variations": { - "post": { - "operationId": "createImageVariation", - "tags": [ - "Images" - ], - "summary": "Creates a variation of a given image.", - "requestBody": { - "required": true, - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/CreateImageVariationRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImagesResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create image variation", - "group": "images", - "returns": "Returns a list of [image](/docs/api-reference/images/object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/images/variations \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -F image=\"@otter.png\" \\\n -F n=2 \\\n -F size=\"1024x1024\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nresponse = client.images.create_variation(\n image=open(\"image_edit_original.png\", \"rb\"),\n n=2,\n size=\"1024x1024\"\n)\n", - "node.js": "import fs from \"fs\";\nimport OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const image = await openai.images.createVariation({\n image: fs.createReadStream(\"otter.png\"),\n });\n\n console.log(image.data);\n}\nmain();" - }, - "response": "{\n \"created\": 1589478378,\n \"data\": [\n {\n \"url\": \"https://...\"\n },\n {\n \"url\": \"https://...\"\n }\n ]\n}\n" - } - } - } - }, - "/embeddings": { - "post": { - "operationId": "createEmbedding", - "tags": [ - "Embeddings" - ], - "summary": "Creates an embedding vector representing the input text.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateEmbeddingRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateEmbeddingResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create embeddings", - "group": "embeddings", - "returns": "A list of [embedding](/docs/api-reference/embeddings/object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/embeddings \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"input\": \"The food was delicious and the waiter...\",\n \"model\": \"text-embedding-ada-002\",\n \"encoding_format\": \"float\"\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.embeddings.create(\n model=\"text-embedding-ada-002\",\n input=\"The food was delicious and the waiter...\",\n encoding_format=\"float\"\n)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const embedding = await openai.embeddings.create({\n model: \"text-embedding-ada-002\",\n input: \"The quick brown fox jumped over the lazy dog\",\n encoding_format: \"float\",\n });\n\n console.log(embedding);\n}\n\nmain();" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"object\": \"embedding\",\n \"embedding\": [\n 0.0023064255,\n -0.009327292,\n .... (1536 floats total for ada-002)\n -0.0028842222,\n ],\n \"index\": 0\n }\n ],\n \"model\": \"text-embedding-ada-002\",\n \"usage\": {\n \"prompt_tokens\": 8,\n \"total_tokens\": 8\n }\n}\n" - } - } - } - }, - "/audio/speech": { - "post": { - "operationId": "createSpeech", - "tags": [ - "Audio" - ], - "summary": "Generates audio from the input text.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSpeechRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "headers": { - "Transfer-Encoding": { - "schema": { - "type": "string" - }, - "description": "chunked" - } - }, - "content": { - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create speech", - "group": "audio", - "returns": "The audio file content.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/audio/speech \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"model\": \"tts-1\",\n \"input\": \"The quick brown fox jumped over the lazy dog.\",\n \"voice\": \"alloy\"\n }' \\\n --output speech.mp3\n", - "python": "from pathlib import Path\nimport openai\n\nspeech_file_path = Path(__file__).parent / \"speech.mp3\"\nresponse = openai.audio.speech.create(\n model=\"tts-1\",\n voice=\"alloy\",\n input=\"The quick brown fox jumped over the lazy dog.\"\n)\nresponse.stream_to_file(speech_file_path)\n", - "node": "import fs from \"fs\";\nimport path from \"path\";\nimport OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nconst speechFile = path.resolve(\"./speech.mp3\");\n\nasync function main() {\n const mp3 = await openai.audio.speech.create({\n model: \"tts-1\",\n voice: \"alloy\",\n input: \"Today is a wonderful day to build something people love!\",\n });\n console.log(speechFile);\n const buffer = Buffer.from(await mp3.arrayBuffer());\n await fs.promises.writeFile(speechFile, buffer);\n}\nmain();\n" - } - } - } - } - }, - "/audio/transcriptions": { - "post": { - "operationId": "createTranscription", - "tags": [ - "Audio" - ], - "summary": "Transcribes audio into the input language.", - "requestBody": { - "required": true, - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/CreateTranscriptionRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTranscriptionResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create transcription", - "group": "audio", - "returns": "The transcribed text.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/audio/transcriptions \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: multipart/form-data\" \\\n -F file=\"@/path/to/file/audio.mp3\" \\\n -F model=\"whisper-1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\naudio_file = open(\"speech.mp3\", \"rb\")\ntranscript = client.audio.transcriptions.create(\n model=\"whisper-1\",\n file=audio_file\n)\n", - "node": "import fs from \"fs\";\nimport OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const transcription = await openai.audio.transcriptions.create({\n file: fs.createReadStream(\"audio.mp3\"),\n model: \"whisper-1\",\n });\n\n console.log(transcription.text);\n}\nmain();\n" - }, - "response": "{\n \"text\": \"Imagine the wildest idea that you've ever had, and you're curious about how it might scale to something that's a 100, a 1,000 times bigger. This is a place where you can get to do that.\"\n}\n" - } - } - } - }, - "/audio/translations": { - "post": { - "operationId": "createTranslation", - "tags": [ - "Audio" - ], - "summary": "Translates audio into English.", - "requestBody": { - "required": true, - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/CreateTranslationRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTranslationResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create translation", - "group": "audio", - "returns": "The translated text.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/audio/translations \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: multipart/form-data\" \\\n -F file=\"@/path/to/file/german.m4a\" \\\n -F model=\"whisper-1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\naudio_file = open(\"speech.mp3\", \"rb\")\ntranscript = client.audio.translations.create(\n model=\"whisper-1\",\n file=audio_file\n)\n", - "node": "import fs from \"fs\";\nimport OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const translation = await openai.audio.translations.create({\n file: fs.createReadStream(\"speech.mp3\"),\n model: \"whisper-1\",\n });\n\n console.log(translation.text);\n}\nmain();\n" - }, - "response": "{\n \"text\": \"Hello, my name is Wolfgang and I come from Germany. Where are you heading today?\"\n}\n" - } - } - } - }, - "/files": { - "get": { - "operationId": "listFiles", - "tags": [ - "Files" - ], - "summary": "Returns a list of files that belong to the user's organization.", - "parameters": [ - { - "in": "query", - "name": "purpose", - "required": false, - "schema": { - "type": "string" - }, - "description": "Only return files with the given purpose." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListFilesResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List files", - "group": "files", - "returns": "A list of [File](/docs/api-reference/files/object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/files \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.files.list()\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const list = await openai.files.list();\n\n for await (const file of list) {\n console.log(file);\n }\n}\n\nmain();" - }, - "response": "{\n \"data\": [\n {\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"bytes\": 175,\n \"created_at\": 1613677385,\n \"filename\": \"salesOverview.pdf\",\n \"purpose\": \"assistants\",\n },\n {\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"bytes\": 140,\n \"created_at\": 1613779121,\n \"filename\": \"puppy.jsonl\",\n \"purpose\": \"fine-tune\",\n }\n ],\n \"object\": \"list\"\n}\n" - } - } - }, - "post": { - "operationId": "createFile", - "tags": [ - "Files" - ], - "summary": "Upload a file that can be used across various endpoints. The size of all the files uploaded by one organization can be up to 100 GB.\n\nThe size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files supported. The Fine-tuning API only supports `.jsonl` files.\n\nPlease [contact us](https://help.openai.com/) if you need to increase these storage limits.\n", - "requestBody": { - "required": true, - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/CreateFileRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OpenAIFile" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Upload file", - "group": "files", - "returns": "The uploaded [File](/docs/api-reference/files/object) object.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/files \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -F purpose=\"fine-tune\" \\\n -F file=\"@mydata.jsonl\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.files.create(\n file=open(\"mydata.jsonl\", \"rb\"),\n purpose=\"fine-tune\"\n)\n", - "node.js": "import fs from \"fs\";\nimport OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const file = await openai.files.create({\n file: fs.createReadStream(\"mydata.jsonl\"),\n purpose: \"fine-tune\",\n });\n\n console.log(file);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"bytes\": 120000,\n \"created_at\": 1677610602,\n \"filename\": \"mydata.jsonl\",\n \"purpose\": \"fine-tune\",\n}\n" - } - } - } - }, - "/files/{file_id}": { - "delete": { - "operationId": "deleteFile", - "tags": [ - "Files" - ], - "summary": "Delete a file.", - "parameters": [ - { - "in": "path", - "name": "file_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the file to use for this request." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteFileResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Delete file", - "group": "files", - "returns": "Deletion status.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/files/file-abc123 \\\n -X DELETE \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.files.delete(\"file-abc123\")\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const file = await openai.files.del(\"file-abc123\");\n\n console.log(file);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"deleted\": true\n}\n" - } - } - }, - "get": { - "operationId": "retrieveFile", - "tags": [ - "Files" - ], - "summary": "Returns information about a specific file.", - "parameters": [ - { - "in": "path", - "name": "file_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the file to use for this request." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OpenAIFile" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve file", - "group": "files", - "returns": "The [File](/docs/api-reference/files/object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/files/file-abc123 \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.files.retrieve(\"file-abc123\")\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const file = await openai.files.retrieve(\"file-abc123\");\n\n console.log(file);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"bytes\": 120000,\n \"created_at\": 1677610602,\n \"filename\": \"mydata.jsonl\",\n \"purpose\": \"fine-tune\",\n}\n" - } - } - } - }, - "/files/{file_id}/content": { - "get": { - "operationId": "downloadFile", - "tags": [ - "Files" - ], - "summary": "Returns the contents of the specified file.", - "parameters": [ - { - "in": "path", - "name": "file_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the file to use for this request." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "string" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve file content", - "group": "files", - "returns": "The file content.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/files/file-abc123/content \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" > file.jsonl\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\ncontent = client.files.retrieve_content(\"file-abc123\")\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const file = await openai.files.retrieveContent(\"file-abc123\");\n\n console.log(file);\n}\n\nmain();\n" - } - } - } - } - }, - "/fine_tuning/jobs": { - "post": { - "operationId": "createFineTuningJob", - "tags": [ - "Fine-tuning" - ], - "summary": "Creates a job that fine-tunes a specified model from a given dataset.\n\nResponse includes details of the enqueued job including job status and the name of the fine-tuned models once complete.\n\n[Learn more about fine-tuning](/docs/guides/fine-tuning)\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateFineTuningJobRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FineTuningJob" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create fine-tuning job", - "group": "fine-tuning", - "returns": "A [fine-tuning.job](/docs/api-reference/fine-tuning/object) object.", - "examples": [ - { - "title": "Default", - "request": { - "curl": "curl https://api.openai.com/v1/fine_tuning/jobs \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"training_file\": \"file-BK7bzQj3FfZFXr7DbL6xJwfo\",\n \"model\": \"gpt-3.5-turbo\"\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.fine_tuning.jobs.create(\n training_file=\"file-abc123\",\n model=\"gpt-3.5-turbo\"\n)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const fineTune = await openai.fineTuning.jobs.create({\n training_file: \"file-abc123\"\n });\n\n console.log(fineTune);\n}\n\nmain();\n" - }, - "response": "{\n \"object\": \"fine_tuning.job\",\n \"id\": \"ftjob-abc123\",\n \"model\": \"gpt-3.5-turbo-0613\",\n \"created_at\": 1614807352,\n \"fine_tuned_model\": null,\n \"organization_id\": \"org-123\",\n \"result_files\": [],\n \"status\": \"queued\",\n \"validation_file\": null,\n \"training_file\": \"file-abc123\",\n}\n" - }, - { - "title": "Epochs", - "request": { - "curl": "curl https://api.openai.com/v1/fine_tuning/jobs \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"training_file\": \"file-abc123\",\n \"model\": \"gpt-3.5-turbo\",\n \"hyperparameters\": {\n \"n_epochs\": 2\n }\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.fine_tuning.jobs.create(\n training_file=\"file-abc123\",\n model=\"gpt-3.5-turbo\",\n hyperparameters={\n \"n_epochs\":2\n }\n)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const fineTune = await openai.fineTuning.jobs.create({\n training_file: \"file-abc123\",\n model: \"gpt-3.5-turbo\",\n hyperparameters: { n_epochs: 2 }\n });\n\n console.log(fineTune);\n}\n\nmain();\n" - }, - "response": "{\n \"object\": \"fine_tuning.job\",\n \"id\": \"ftjob-abc123\",\n \"model\": \"gpt-3.5-turbo-0613\",\n \"created_at\": 1614807352,\n \"fine_tuned_model\": null,\n \"organization_id\": \"org-123\",\n \"result_files\": [],\n \"status\": \"queued\",\n \"validation_file\": null,\n \"training_file\": \"file-abc123\",\n \"hyperparameters\": {\"n_epochs\": 2},\n}\n" - }, - { - "title": "Validation file", - "request": { - "curl": "curl https://api.openai.com/v1/fine_tuning/jobs \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"training_file\": \"file-abc123\",\n \"validation_file\": \"file-abc123\",\n \"model\": \"gpt-3.5-turbo\"\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.fine_tuning.jobs.create(\n training_file=\"file-abc123\",\n validation_file=\"file-def456\",\n model=\"gpt-3.5-turbo\"\n)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const fineTune = await openai.fineTuning.jobs.create({\n training_file: \"file-abc123\",\n validation_file: \"file-abc123\"\n });\n\n console.log(fineTune);\n}\n\nmain();\n" - }, - "response": "{\n \"object\": \"fine_tuning.job\",\n \"id\": \"ftjob-abc123\",\n \"model\": \"gpt-3.5-turbo-0613\",\n \"created_at\": 1614807352,\n \"fine_tuned_model\": null,\n \"organization_id\": \"org-123\",\n \"result_files\": [],\n \"status\": \"queued\",\n \"validation_file\": \"file-abc123\",\n \"training_file\": \"file-abc123\",\n}\n" - } - ] - } - }, - "get": { - "operationId": "listPaginatedFineTuningJobs", - "tags": [ - "Fine-tuning" - ], - "summary": "List your organization's fine-tuning jobs\n", - "parameters": [ - { - "name": "after", - "in": "query", - "description": "Identifier for the last job from the previous pagination request.", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Number of fine-tuning jobs to retrieve.", - "required": false, - "schema": { - "type": "integer", - "default": 20 - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListPaginatedFineTuningJobsResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List fine-tuning jobs", - "group": "fine-tuning", - "returns": "A list of paginated [fine-tuning job](/docs/api-reference/fine-tuning/object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/fine_tuning/jobs?limit=2 \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.fine_tuning.jobs.list()\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const list = await openai.fineTuning.jobs.list();\n\n for await (const fineTune of list) {\n console.log(fineTune);\n }\n}\n\nmain();" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"object\": \"fine_tuning.job.event\",\n \"id\": \"ft-event-TjX0lMfOniCZX64t9PUQT5hn\",\n \"created_at\": 1689813489,\n \"level\": \"warn\",\n \"message\": \"Fine tuning process stopping due to job cancellation\",\n \"data\": null,\n \"type\": \"message\"\n },\n { ... },\n { ... }\n ], \"has_more\": true\n}\n" - } - } - } - }, - "/fine_tuning/jobs/{fine_tuning_job_id}": { - "get": { - "operationId": "retrieveFineTuningJob", - "tags": [ - "Fine-tuning" - ], - "summary": "Get info about a fine-tuning job.\n\n[Learn more about fine-tuning](/docs/guides/fine-tuning)\n", - "parameters": [ - { - "in": "path", - "name": "fine_tuning_job_id", - "required": true, - "schema": { - "type": "string", - "example": "ft-AF1WoRqd3aJAHsqc9NY7iL8F" - }, - "description": "The ID of the fine-tuning job.\n" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FineTuningJob" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve fine-tuning job", - "group": "fine-tuning", - "returns": "The [fine-tuning](/docs/api-reference/fine-tunes/object) object with the given ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/fine_tuning/jobs/ft-AF1WoRqd3aJAHsqc9NY7iL8F \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.fine_tuning.jobs.retrieve(\"ftjob-abc123\")\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const fineTune = await openai.fineTuning.jobs.retrieve(\"ftjob-abc123\");\n\n console.log(fineTune);\n}\n\nmain();\n" - }, - "response": "{\n \"object\": \"fine_tuning.job\",\n \"id\": \"ftjob-abc123\",\n \"model\": \"davinci-002\",\n \"created_at\": 1692661014,\n \"finished_at\": 1692661190,\n \"fine_tuned_model\": \"ft:davinci-002:my-org:custom_suffix:7q8mpxmy\",\n \"organization_id\": \"org-123\",\n \"result_files\": [\n \"file-abc123\"\n ],\n \"status\": \"succeeded\",\n \"validation_file\": null,\n \"training_file\": \"file-abc123\",\n \"hyperparameters\": {\n \"n_epochs\": 4,\n },\n \"trained_tokens\": 5768\n}\n" - } - } - } - }, - "/fine_tuning/jobs/{fine_tuning_job_id}/events": { - "get": { - "operationId": "listFineTuningEvents", - "tags": [ - "Fine-tuning" - ], - "summary": "Get status updates for a fine-tuning job.\n", - "parameters": [ - { - "in": "path", - "name": "fine_tuning_job_id", - "required": true, - "schema": { - "type": "string", - "example": "ft-AF1WoRqd3aJAHsqc9NY7iL8F" - }, - "description": "The ID of the fine-tuning job to get events for.\n" - }, - { - "name": "after", - "in": "query", - "description": "Identifier for the last event from the previous pagination request.", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Number of events to retrieve.", - "required": false, - "schema": { - "type": "integer", - "default": 20 - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListFineTuningJobEventsResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List fine-tuning events", - "group": "fine-tuning", - "returns": "A list of fine-tuning event objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/fine_tuning/jobs/ftjob-abc123/events \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.fine_tuning.jobs.list_events(\n fine_tuning_job_id=\"ftjob-abc123\",\n limit=2\n)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const list = await openai.fineTuning.list_events(id=\"ftjob-abc123\", limit=2);\n\n for await (const fineTune of list) {\n console.log(fineTune);\n }\n}\n\nmain();" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"object\": \"fine_tuning.job.event\",\n \"id\": \"ft-event-ddTJfwuMVpfLXseO0Am0Gqjm\",\n \"created_at\": 1692407401,\n \"level\": \"info\",\n \"message\": \"Fine tuning job successfully completed\",\n \"data\": null,\n \"type\": \"message\"\n },\n {\n \"object\": \"fine_tuning.job.event\",\n \"id\": \"ft-event-tyiGuB72evQncpH87xe505Sv\",\n \"created_at\": 1692407400,\n \"level\": \"info\",\n \"message\": \"New fine-tuned model created: ft:gpt-3.5-turbo:openai::7p4lURel\",\n \"data\": null,\n \"type\": \"message\"\n }\n ],\n \"has_more\": true\n}\n" - } - } - } - }, - "/fine_tuning/jobs/{fine_tuning_job_id}/cancel": { - "post": { - "operationId": "cancelFineTuningJob", - "tags": [ - "Fine-tuning" - ], - "summary": "Immediately cancel a fine-tune job.\n", - "parameters": [ - { - "in": "path", - "name": "fine_tuning_job_id", - "required": true, - "schema": { - "type": "string", - "example": "ft-AF1WoRqd3aJAHsqc9NY7iL8F" - }, - "description": "The ID of the fine-tuning job to cancel.\n" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FineTuningJob" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Cancel fine-tuning", - "group": "fine-tuning", - "returns": "The cancelled [fine-tuning](/docs/api-reference/fine-tuning/object) object.", - "examples": { - "request": { - "curl": "curl -X POST https://api.openai.com/v1/fine_tuning/jobs/ftjob-abc123/cancel \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.fine_tuning.jobs.cancel(\"ftjob-abc123\")\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const fineTune = await openai.fineTuning.jobs.cancel(\"ftjob-abc123\");\n\n console.log(fineTune);\n}\nmain();" - }, - "response": "{\n \"object\": \"fine_tuning.job\",\n \"id\": \"ftjob-abc123\",\n \"model\": \"gpt-3.5-turbo-0613\",\n \"created_at\": 1689376978,\n \"fine_tuned_model\": null,\n \"organization_id\": \"org-123\",\n \"result_files\": [],\n \"hyperparameters\": {\n \"n_epochs\": \"auto\"\n },\n \"status\": \"cancelled\",\n \"validation_file\": \"file-abc123\",\n \"training_file\": \"file-abc123\"\n}\n" - } - } - } - }, - "/fine-tunes": { - "post": { - "operationId": "createFineTune", - "deprecated": true, - "tags": [ - "Fine-tunes" - ], - "summary": "Creates a job that fine-tunes a specified model from a given dataset.\n\nResponse includes details of the enqueued job including job status and the name of the fine-tuned models once complete.\n\n[Learn more about fine-tuning](/docs/guides/legacy-fine-tuning)\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateFineTuneRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FineTune" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create fine-tune", - "group": "fine-tunes", - "returns": "A [fine-tune](/docs/api-reference/fine-tunes/object) object.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/fine-tunes \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"training_file\": \"file-abc123\"\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nfine_tune = client.fine_tunes.create(\n training_file=\"file-abc123\",\n model=\"davinci\"\n}\nprint(fine_tune)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const fineTune = await openai.fineTunes.create({\n training_file: \"file-abc123\"\n });\n\n console.log(fineTune);\n}\n\nmain();\n" - }, - "response": "{\n \"id\": \"ft-AF1WoRqd3aJAHsqc9NY7iL8F\",\n \"object\": \"fine-tune\",\n \"model\": \"curie\",\n \"created_at\": 1614807352,\n \"events\": [\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807352,\n \"level\": \"info\",\n \"message\": \"Job enqueued. Waiting for jobs ahead to complete. Queue number: 0.\"\n }\n ],\n \"fine_tuned_model\": null,\n \"hyperparams\": {\n \"batch_size\": 4,\n \"learning_rate_multiplier\": 0.1,\n \"n_epochs\": 4,\n \"prompt_loss_weight\": 0.1,\n },\n \"organization_id\": \"org-123\",\n \"result_files\": [],\n \"status\": \"pending\",\n \"validation_files\": [],\n \"training_files\": [\n {\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"bytes\": 1547276,\n \"created_at\": 1610062281,\n \"filename\": \"my-data-train.jsonl\",\n \"purpose\": \"fine-tune-results\"\n }\n ],\n \"updated_at\": 1614807352,\n}\n" - } - } - }, - "get": { - "operationId": "listFineTunes", - "deprecated": true, - "tags": [ - "Fine-tunes" - ], - "summary": "List your organization's fine-tuning jobs\n", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListFineTunesResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List fine-tunes", - "group": "fine-tunes", - "returns": "A list of [fine-tune](/docs/api-reference/fine-tunes/object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/fine-tunes \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmodels = client.fine_tunes.list()\nprint(models)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const list = await openai.fineTunes.list();\n\n for await (const fineTune of list) {\n console.log(fineTune);\n }\n}\n\nmain();" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"id\": \"ft-AF1WoRqd3aJAHsqc9NY7iL8F\",\n \"object\": \"fine-tune\",\n \"model\": \"curie\",\n \"created_at\": 1614807352,\n \"fine_tuned_model\": null,\n \"hyperparams\": { ... },\n \"organization_id\": \"org-123\",\n \"result_files\": [],\n \"status\": \"pending\",\n \"validation_files\": [],\n \"training_files\": [ { ... } ],\n \"updated_at\": 1614807352,\n },\n { ... },\n { ... }\n ]\n}\n" - } - } - } - }, - "/fine-tunes/{fine_tune_id}": { - "get": { - "operationId": "retrieveFineTune", - "deprecated": true, - "tags": [ - "Fine-tunes" - ], - "summary": "Gets info about the fine-tune job.\n\n[Learn more about fine-tuning](/docs/guides/legacy-fine-tuning)\n", - "parameters": [ - { - "in": "path", - "name": "fine_tune_id", - "required": true, - "schema": { - "type": "string", - "example": "ft-AF1WoRqd3aJAHsqc9NY7iL8F" - }, - "description": "The ID of the fine-tune job\n" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FineTune" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve fine-tune", - "group": "fine-tunes", - "returns": "The [fine-tune](/docs/api-reference/fine-tunes/object) object with the given ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/fine-tunes/ft-abc123 \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nfine_tune = client.fine_tunes.retrieve(\"ft-abc123\")\nprint(fine_tune)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const fineTune = await openai.fineTunes.retrieve(\"ft-abc123\");\n\n console.log(fineTune);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"ft-abc123\",\n \"object\": \"fine-tune\",\n \"model\": \"curie\",\n \"created_at\": 1614807352,\n \"events\": [\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807352,\n \"level\": \"info\",\n \"message\": \"Job enqueued. Waiting for jobs ahead to complete. Queue number: 0.\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807356,\n \"level\": \"info\",\n \"message\": \"Job started.\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807861,\n \"level\": \"info\",\n \"message\": \"Uploaded snapshot: curie:ft-acmeco-2021-03-03-21-44-20.\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807864,\n \"level\": \"info\",\n \"message\": \"Uploaded result files: file-abc123.\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807864,\n \"level\": \"info\",\n \"message\": \"Job succeeded.\"\n }\n ],\n \"fine_tuned_model\": \"curie:ft-acmeco-2021-03-03-21-44-20\",\n \"hyperparams\": {\n \"batch_size\": 4,\n \"learning_rate_multiplier\": 0.1,\n \"n_epochs\": 4,\n \"prompt_loss_weight\": 0.1,\n },\n \"organization_id\": \"org-123\",\n \"result_files\": [\n {\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"bytes\": 81509,\n \"created_at\": 1614807863,\n \"filename\": \"compiled_results.csv\",\n \"purpose\": \"fine-tune-results\"\n }\n ],\n \"status\": \"succeeded\",\n \"validation_files\": [],\n \"training_files\": [\n {\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"bytes\": 1547276,\n \"created_at\": 1610062281,\n \"filename\": \"my-data-train.jsonl\",\n \"purpose\": \"fine-tune\"\n }\n ],\n \"updated_at\": 1614807865,\n}\n" - } - } - } - }, - "/fine-tunes/{fine_tune_id}/cancel": { - "post": { - "operationId": "cancelFineTune", - "deprecated": true, - "tags": [ - "Fine-tunes" - ], - "summary": "Immediately cancel a fine-tune job.\n", - "parameters": [ - { - "in": "path", - "name": "fine_tune_id", - "required": true, - "schema": { - "type": "string", - "example": "ft-AF1WoRqd3aJAHsqc9NY7iL8F" - }, - "description": "The ID of the fine-tune job to cancel\n" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FineTune" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Cancel fine-tune", - "group": "fine-tunes", - "returns": "The cancelled [fine-tune](/docs/api-reference/fine-tunes/object) object.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/fine-tunes/ft-AF1WoRqd3aJAHsqc9NY7iL8F/cancel \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nfine_tune = client.fine_tunes.cancel(\"ft-abc123\")\nprint(fine_tune)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const fineTune = await openai.fineTunes.cancel(\"ft-AF1WoRqd3aJAHsqc9NY7iL8F\");\n\n console.log(fineTune);\n}\nmain();" - }, - "response": "{\n \"id\": \"ft-xhrpBbvVUzYGo8oUO1FY4nI7\",\n \"object\": \"fine-tune\",\n \"model\": \"curie\",\n \"created_at\": 1614807770,\n \"events\": [ { ... } ],\n \"fine_tuned_model\": null,\n \"hyperparams\": { ... },\n \"organization_id\": \"org-123\",\n \"result_files\": [],\n \"status\": \"cancelled\",\n \"validation_files\": [],\n \"training_files\": [\n {\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"bytes\": 1547276,\n \"created_at\": 1610062281,\n \"filename\": \"my-data-train.jsonl\",\n \"purpose\": \"fine-tune\"\n }\n ],\n \"updated_at\": 1614807789,\n}\n" - } - } - } - }, - "/fine-tunes/{fine_tune_id}/events": { - "get": { - "operationId": "listFineTuneEvents", - "deprecated": true, - "tags": [ - "Fine-tunes" - ], - "summary": "Get fine-grained status updates for a fine-tune job.\n", - "parameters": [ - { - "in": "path", - "name": "fine_tune_id", - "required": true, - "schema": { - "type": "string", - "example": "ft-AF1WoRqd3aJAHsqc9NY7iL8F" - }, - "description": "The ID of the fine-tune job to get events for.\n" - }, - { - "in": "query", - "name": "stream", - "required": false, - "schema": { - "type": "boolean", - "default": false - }, - "description": "Whether to stream events for the fine-tune job. If set to true,\nevents will be sent as data-only\n[server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format)\nas they become available. The stream will terminate with a\n`data: [DONE]` message when the job is finished (succeeded, cancelled,\nor failed).\n\nIf set to false, only events generated so far will be returned.\n" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListFineTuneEventsResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List fine-tune events", - "group": "fine-tunes", - "returns": "A list of fine-tune event objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/fine-tunes/ft-AF1WoRqd3aJAHsqc9NY7iL8F/events \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nfine_tune = client.fine_tunes.list_events(\"ft-abc123\")\nprint(fine_tune)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const fineTune = await openai.fineTunes.listEvents(\"ft-AF1WoRqd3aJAHsqc9NY7iL8F\");\n\n console.log(fineTune);\n}\nmain();" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807352,\n \"level\": \"info\",\n \"message\": \"Job enqueued. Waiting for jobs ahead to complete. Queue number: 0.\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807356,\n \"level\": \"info\",\n \"message\": \"Job started.\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807861,\n \"level\": \"info\",\n \"message\": \"Uploaded snapshot: curie:ft-acmeco-2021-03-03-21-44-20.\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807864,\n \"level\": \"info\",\n \"message\": \"Uploaded result files: file-abc123\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807864,\n \"level\": \"info\",\n \"message\": \"Job succeeded.\"\n }\n ]\n}\n" - } - } - } - }, - "/models": { - "get": { - "operationId": "listModels", - "tags": [ - "Models" - ], - "summary": "Lists the currently available models, and provides basic information about each one such as the owner and availability.", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListModelsResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List models", - "group": "models", - "returns": "A list of [model](/docs/api-reference/models/object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/models \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.models.list()\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const list = await openai.models.list();\n\n for await (const model of list) {\n console.log(model);\n }\n}\nmain();" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"id\": \"model-id-0\",\n \"object\": \"model\",\n \"created\": 1686935002,\n \"owned_by\": \"organization-owner\"\n },\n {\n \"id\": \"model-id-1\",\n \"object\": \"model\",\n \"created\": 1686935002,\n \"owned_by\": \"organization-owner\",\n },\n {\n \"id\": \"model-id-2\",\n \"object\": \"model\",\n \"created\": 1686935002,\n \"owned_by\": \"openai\"\n },\n ],\n \"object\": \"list\"\n}\n" - } - } - } - }, - "/models/{model}": { - "get": { - "operationId": "retrieveModel", - "tags": [ - "Models" - ], - "summary": "Retrieves a model instance, providing basic information about the model such as the owner and permissioning.", - "parameters": [ - { - "in": "path", - "name": "model", - "required": true, - "schema": { - "type": "string", - "example": "gpt-3.5-turbo" - }, - "description": "The ID of the model to use for this request" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Model" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve model", - "group": "models", - "returns": "The [model](/docs/api-reference/models/object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/models/VAR_model_id \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.models.retrieve(\"VAR_model_id\")\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const model = await openai.models.retrieve(\"gpt-3.5-turbo\");\n\n console.log(model);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"VAR_model_id\",\n \"object\": \"model\",\n \"created\": 1686935002,\n \"owned_by\": \"openai\"\n}\n" - } - } - }, - "delete": { - "operationId": "deleteModel", - "tags": [ - "Models" - ], - "summary": "Delete a fine-tuned model. You must have the Owner role in your organization to delete a model.", - "parameters": [ - { - "in": "path", - "name": "model", - "required": true, - "schema": { - "type": "string", - "example": "ft:gpt-3.5-turbo:acemeco:suffix:abc123" - }, - "description": "The model to delete" - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteModelResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Delete a fine-tuned model", - "group": "models", - "returns": "Deletion status.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/models/ft:gpt-3.5-turbo:acemeco:suffix:abc123 \\\n -X DELETE \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.models.delete(\"ft:gpt-3.5-turbo:acemeco:suffix:abc123\")\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const model = await openai.models.del(\"ft:gpt-3.5-turbo:acemeco:suffix:abc123\");\n\n console.log(model);\n}\nmain();" - }, - "response": "{\n \"id\": \"ft:gpt-3.5-turbo:acemeco:suffix:abc123\",\n \"object\": \"model\",\n \"deleted\": true\n}\n" - } - } - } - }, - "/moderations": { - "post": { - "operationId": "createModeration", - "tags": [ - "Moderations" - ], - "summary": "Classifies if text violates OpenAI's Content Policy", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateModerationRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateModerationResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create moderation", - "group": "moderations", - "returns": "A [moderation](/docs/api-reference/moderations/object) object.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/moderations \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -d '{\n \"input\": \"I want to kill them.\"\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nclient.moderations.create(input=\"I want to kill them.\")\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const moderation = await openai.moderations.create({ input: \"I want to kill them.\" });\n\n console.log(moderation);\n}\nmain();\n" - }, - "response": "{\n \"id\": \"modr-XXXXX\",\n \"model\": \"text-moderation-005\",\n \"results\": [\n {\n \"flagged\": true,\n \"categories\": {\n \"sexual\": false,\n \"hate\": false,\n \"harassment\": false,\n \"self-harm\": false,\n \"sexual/minors\": false,\n \"hate/threatening\": false,\n \"violence/graphic\": false,\n \"self-harm/intent\": false,\n \"self-harm/instructions\": false,\n \"harassment/threatening\": true,\n \"violence\": true,\n },\n \"category_scores\": {\n \"sexual\": 1.2282071e-06,\n \"hate\": 0.010696256,\n \"harassment\": 0.29842457,\n \"self-harm\": 1.5236925e-08,\n \"sexual/minors\": 5.7246268e-08,\n \"hate/threatening\": 0.0060676364,\n \"violence/graphic\": 4.435014e-06,\n \"self-harm/intent\": 8.098441e-10,\n \"self-harm/instructions\": 2.8498655e-11,\n \"harassment/threatening\": 0.63055265,\n \"violence\": 0.99011886,\n }\n }\n ]\n}\n" - } - } - } - }, - "/assistants": { - "get": { - "operationId": "listAssistants", - "tags": [ - "Assistants" - ], - "summary": "Returns a list of assistants.", - "parameters": [ - { - "name": "limit", - "in": "query", - "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20.\n", - "required": false, - "schema": { - "type": "integer", - "default": 20 - } - }, - { - "name": "order", - "in": "query", - "description": "Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order.\n", - "schema": { - "type": "string", - "default": "desc", - "enum": [ - "asc", - "desc" - ] - } - }, - { - "name": "after", - "in": "query", - "description": "A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list.\n", - "schema": { - "type": "string" - } - }, - { - "name": "before", - "in": "query", - "description": "A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list.\n", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListAssistantsResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List assistants", - "group": "assistants", - "beta": true, - "returns": "A list of [assistant](/docs/api-reference/assistants/object) objects.", - "examples": { - "request": { - "curl": "curl \"https://api.openai.com/v1/assistants?order=desc&limit=20\" \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmy_assistants = client.beta.assistants.list(\n order=\"desc\",\n limit=\"20\",\n)\nprint(my_assistants.data)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const myAssistants = await openai.beta.assistants.list({\n order: \"desc\",\n limit: \"20\",\n });\n\n console.log(myAssistants.data);\n}\n\nmain();" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"id\": \"asst_abc123\",\n \"object\": \"assistant\",\n \"created_at\": 1698982736,\n \"name\": \"Coding Tutor\",\n \"description\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You are a helpful assistant designed to make me better at coding!\",\n \"tools\": [],\n \"file_ids\": [],\n \"metadata\": {}\n },\n {\n \"id\": \"asst_abc456\",\n \"object\": \"assistant\",\n \"created_at\": 1698982718,\n \"name\": \"My Assistant\",\n \"description\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You are a helpful assistant designed to make me better at coding!\",\n \"tools\": [],\n \"file_ids\": [],\n \"metadata\": {}\n },\n {\n \"id\": \"asst_abc789\",\n \"object\": \"assistant\",\n \"created_at\": 1698982643,\n \"name\": null,\n \"description\": null,\n \"model\": \"gpt-4\",\n \"instructions\": null,\n \"tools\": [],\n \"file_ids\": [],\n \"metadata\": {}\n }\n ],\n \"first_id\": \"asst_abc123\",\n \"last_id\": \"asst_abc789\",\n \"has_more\": false\n}\n" - } - } - }, - "post": { - "operationId": "createAssistant", - "tags": [ - "Assistants" - ], - "summary": "Create an assistant with a model and instructions.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateAssistantRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AssistantObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create assistant", - "group": "assistants", - "beta": true, - "returns": "An [assistant](/docs/api-reference/assistants/object) object.", - "examples": [ - { - "title": "Code Interpreter", - "request": { - "curl": "curl \"https://api.openai.com/v1/assistants\" \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -d '{\n \"instructions\": \"You are a personal math tutor. When asked a question, write and run Python code to answer the question.\",\n \"name\": \"Math Tutor\",\n \"tools\": [{\"type\": \"code_interpreter\"}],\n \"model\": \"gpt-4\"\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmy_assistant = client.beta.assistants.create(\n instructions=\"You are a personal math tutor. When asked a question, write and run Python code to answer the question.\",\n name=\"Math Tutor\",\n tools=[{\"type\": \"code_interpreter\"}],\n model=\"gpt-4\",\n)\nprint(my_assistant)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const myAssistant = await openai.beta.assistants.create({\n instructions:\n \"You are a personal math tutor. When asked a question, write and run Python code to answer the question.\",\n name: \"Math Tutor\",\n tools: [{ type: \"code_interpreter\" }],\n model: \"gpt-4\",\n });\n\n console.log(myAssistant);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"asst_abc123\",\n \"object\": \"assistant\",\n \"created_at\": 1698984975,\n \"name\": \"Math Tutor\",\n \"description\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You are a personal math tutor. When asked a question, write and run Python code to answer the question.\",\n \"tools\": [\n {\n \"type\": \"code_interpreter\"\n }\n ],\n \"file_ids\": [],\n \"metadata\": {}\n}\n" - }, - { - "title": "Files", - "request": { - "curl": "curl https://api.openai.com/v1/assistants \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -d '{\n \"instructions\": \"You are an HR bot, and you have access to files to answer employee questions about company policies.\",\n \"tools\": [{\"type\": \"retrieval\"}],\n \"model\": \"gpt-4\",\n \"file_ids\": [\"file-abc123\"]\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmy_assistant = client.beta.assistants.create(\n instructions=\"You are an HR bot, and you have access to files to answer employee questions about company policies.\",\n name=\"HR Helper\",\n tools=[{\"type\": \"retrieval\"}],\n model=\"gpt-4\",\n file_ids=[\"file-abc123\"],\n)\nprint(my_assistant)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const myAssistant = await openai.beta.assistants.create({\n instructions:\n \"You are an HR bot, and you have access to files to answer employee questions about company policies.\",\n name: \"HR Helper\",\n tools: [{ type: \"retrieval\" }],\n model: \"gpt-4\",\n file_ids: [\"file-abc123\"],\n });\n\n console.log(myAssistant);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"asst_abc123\",\n \"object\": \"assistant\",\n \"created_at\": 1699009403,\n \"name\": \"HR Helper\",\n \"description\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You are an HR bot, and you have access to files to answer employee questions about company policies.\",\n \"tools\": [\n {\n \"type\": \"retrieval\"\n }\n ],\n \"file_ids\": [\n \"file-abc123\"\n ],\n \"metadata\": {}\n}\n" - } - ] - } - } - }, - "/assistants/{assistant_id}": { - "get": { - "operationId": "getAssistant", - "tags": [ - "Assistants" - ], - "summary": "Retrieves an assistant.", - "parameters": [ - { - "in": "path", - "name": "assistant_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the assistant to retrieve." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AssistantObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve assistant", - "group": "assistants", - "beta": true, - "returns": "The [assistant](/docs/api-reference/assistants/object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/assistants/asst_abc123 \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmy_assistant = client.beta.assistants.retrieve(\"asst_abc123\")\nprint(my_assistant)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const myAssistant = await openai.beta.assistants.retrieve(\n \"asst_abc123\"\n );\n\n console.log(myAssistant);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"asst_abc123\",\n \"object\": \"assistant\",\n \"created_at\": 1699009709,\n \"name\": \"HR Helper\",\n \"description\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You are an HR bot, and you have access to files to answer employee questions about company policies.\",\n \"tools\": [\n {\n \"type\": \"retrieval\"\n }\n ],\n \"file_ids\": [\n \"file-abc123\"\n ],\n \"metadata\": {}\n}\n" - } - } - }, - "post": { - "operationId": "modifyAssistant", - "tags": [ - "Assistants" - ], - "summary": "Modifies an assistant.", - "parameters": [ - { - "in": "path", - "name": "assistant_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the assistant to modify." - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModifyAssistantRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AssistantObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Modify assistant", - "group": "assistants", - "beta": true, - "returns": "The modified [assistant](/docs/api-reference/assistants/object) object.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/assistants/asst_abc123 \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -d '{\n \"instructions\": \"You are an HR bot, and you have access to files to answer employee questions about company policies. Always response with info from either of the files.\",\n \"tools\": [{\"type\": \"retrieval\"}],\n \"model\": \"gpt-4\",\n \"file_ids\": [\"file-abc123\", \"file-abc456\"]\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmy_updated_assistant = client.beta.assistants.update(\n \"asst_abc123\",\n instructions=\"You are an HR bot, and you have access to files to answer employee questions about company policies. Always response with info from either of the files.\",\n name=\"HR Helper\",\n tools=[{\"type\": \"retrieval\"}],\n model=\"gpt-4\",\n file_ids=[\"file-abc123\", \"file-abc456\"],\n)\n\nprint(my_updated_assistant)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const myUpdatedAssistant = await openai.beta.assistants.update(\n \"asst_abc123\",\n {\n instructions:\n \"You are an HR bot, and you have access to files to answer employee questions about company policies. Always response with info from either of the files.\",\n name: \"HR Helper\",\n tools: [{ type: \"retrieval\" }],\n model: \"gpt-4\",\n file_ids: [\n \"file-abc123\",\n \"file-abc456\",\n ],\n }\n );\n\n console.log(myUpdatedAssistant);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"asst_abc123\",\n \"object\": \"assistant\",\n \"created_at\": 1699009709,\n \"name\": \"HR Helper\",\n \"description\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You are an HR bot, and you have access to files to answer employee questions about company policies. Always response with info from either of the files.\",\n \"tools\": [\n {\n \"type\": \"retrieval\"\n }\n ],\n \"file_ids\": [\n \"file-abc123\",\n \"file-abc456\"\n ],\n \"metadata\": {}\n}\n" - } - } - }, - "delete": { - "operationId": "deleteAssistant", - "tags": [ - "Assistants" - ], - "summary": "Delete an assistant.", - "parameters": [ - { - "in": "path", - "name": "assistant_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the assistant to delete." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteAssistantResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Delete assistant", - "group": "assistants", - "beta": true, - "returns": "Deletion status", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/assistants/asst_abc123 \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -X DELETE\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nresponse = client.beta.assistants.delete(\"asst_abc123\")\nprint(response)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const response = await openai.beta.assistants.del(\"asst_abc123\");\n\n console.log(response);\n}\nmain();" - }, - "response": "{\n \"id\": \"asst_abc123\",\n \"object\": \"assistant.deleted\",\n \"deleted\": true\n}\n" - } - } - } - }, - "/threads": { - "post": { - "operationId": "createThread", - "tags": [ - "Assistants" - ], - "summary": "Create a thread.", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateThreadRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ThreadObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create thread", - "group": "threads", - "beta": true, - "returns": "A [thread](/docs/api-reference/threads) object.", - "examples": [ - { - "title": "Empty", - "request": { - "curl": "curl https://api.openai.com/v1/threads \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -d ''\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nempty_thread = client.beta.threads.create()\nprint(empty_thread)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const emptyThread = await openai.beta.threads.create();\n\n console.log(emptyThread);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"thread_abc123\",\n \"object\": \"thread\",\n \"created_at\": 1699012949,\n \"metadata\": {}\n}\n" - }, - { - "title": "Messages", - "request": { - "curl": "curl https://api.openai.com/v1/threads \\\n-H \"Content-Type: application/json\" \\\n-H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n-H \"OpenAI-Beta: assistants=v1\" \\\n-d '{\n \"messages\": [{\n \"role\": \"user\",\n \"content\": \"Hello, what is AI?\",\n \"file_ids\": [\"file-abc123\"]\n }, {\n \"role\": \"user\",\n \"content\": \"How does AI work? Explain it in simple terms.\"\n }]\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmessage_thread = client.beta.threads.create(\n messages=[\n {\n \"role\": \"user\",\n \"content\": \"Hello, what is AI?\",\n \"file_ids\": [\"file-abc123\"],\n },\n {\n \"role\": \"user\",\n \"content\": \"How does AI work? Explain it in simple terms.\"\n },\n ]\n)\n\nprint(message_thread)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const messageThread = await openai.beta.threads.create({\n messages: [\n {\n role: \"user\",\n content: \"Hello, what is AI?\",\n file_ids: [\"file-abc123\"],\n },\n {\n role: \"user\",\n content: \"How does AI work? Explain it in simple terms.\",\n },\n ],\n });\n\n console.log(messageThread);\n}\n\nmain();" - }, - "response": "{\n id: 'thread_abc123',\n object: 'thread',\n created_at: 1699014083,\n metadata: {}\n}\n" - } - ] - } - } - }, - "/threads/{thread_id}": { - "get": { - "operationId": "getThread", - "tags": [ - "Assistants" - ], - "summary": "Retrieves a thread.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the thread to retrieve." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ThreadObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve thread", - "group": "threads", - "beta": true, - "returns": "The [thread](/docs/api-reference/threads/object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123 \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmy_thread = client.beta.threads.retrieve(\"thread_abc123\")\nprint(my_thread)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const myThread = await openai.beta.threads.retrieve(\n \"thread_abc123\"\n );\n\n console.log(myThread);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"thread_abc123\",\n \"object\": \"thread\",\n \"created_at\": 1699014083,\n \"metadata\": {}\n}\n" - } - } - }, - "post": { - "operationId": "modifyThread", - "tags": [ - "Assistants" - ], - "summary": "Modifies a thread.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the thread to modify. Only the `metadata` can be modified." - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModifyThreadRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ThreadObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Modify thread", - "group": "threads", - "beta": true, - "returns": "The modified [thread](/docs/api-reference/threads/object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123 \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -d '{\n \"metadata\": {\n \"modified\": \"true\",\n \"user\": \"abc123\"\n }\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmy_updated_thread = client.beta.threads.update(\n \"thread_abc123\",\n metadata={\n \"modified\": \"true\",\n \"user\": \"abc123\"\n }\n)\nprint(my_updated_thread)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const updatedThread = await openai.beta.threads.update(\n \"thread_abc123\",\n {\n metadata: { modified: \"true\", user: \"abc123\" },\n }\n );\n\n console.log(updatedThread);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"thread_abc123\",\n \"object\": \"thread\",\n \"created_at\": 1699014083,\n \"metadata\": {\n \"modified\": \"true\",\n \"user\": \"abc123\"\n }\n}\n" - } - } - }, - "delete": { - "operationId": "deleteThread", - "tags": [ - "Assistants" - ], - "summary": "Delete a thread.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the thread to delete." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteThreadResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Delete thread", - "group": "threads", - "beta": true, - "returns": "Deletion status", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123 \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -X DELETE\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nresponse = client.beta.threads.delete(\"thread_abc123\")\nprint(response)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const response = await openai.beta.threads.del(\"thread_abc123\");\n\n console.log(response);\n}\nmain();" - }, - "response": "{\n \"id\": \"thread_abc123\",\n \"object\": \"thread.deleted\",\n \"deleted\": true\n}\n" - } - } - } - }, - "/threads/{thread_id}/messages": { - "get": { - "operationId": "listMessages", - "tags": [ - "Assistants" - ], - "summary": "Returns a list of messages for a given thread.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the [thread](/docs/api-reference/threads) the messages belong to." - }, - { - "name": "limit", - "in": "query", - "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20.\n", - "required": false, - "schema": { - "type": "integer", - "default": 20 - } - }, - { - "name": "order", - "in": "query", - "description": "Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order.\n", - "schema": { - "type": "string", - "default": "desc", - "enum": [ - "asc", - "desc" - ] - } - }, - { - "name": "after", - "in": "query", - "description": "A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list.\n", - "schema": { - "type": "string" - } - }, - { - "name": "before", - "in": "query", - "description": "A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list.\n", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListMessagesResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List messages", - "group": "threads", - "beta": true, - "returns": "A list of [message](/docs/api-reference/messages) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/messages \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nthread_messages = client.beta.threads.messages.list(\"thread_abc123\")\nprint(thread_messages.data)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const threadMessages = await openai.beta.threads.messages.list(\n \"thread_abc123\"\n );\n\n console.log(threadMessages.data);\n}\n\nmain();" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"id\": \"msg_abc123\",\n \"object\": \"thread.message\",\n \"created_at\": 1699016383,\n \"thread_id\": \"thread_abc123\",\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": {\n \"value\": \"How does AI work? Explain it in simple terms.\",\n \"annotations\": []\n }\n }\n ],\n \"file_ids\": [],\n \"assistant_id\": null,\n \"run_id\": null,\n \"metadata\": {}\n },\n {\n \"id\": \"msg_abc456\",\n \"object\": \"thread.message\",\n \"created_at\": 1699016383,\n \"thread_id\": \"thread_abc123\",\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": {\n \"value\": \"Hello, what is AI?\",\n \"annotations\": []\n }\n }\n ],\n \"file_ids\": [\n \"file-abc123\"\n ],\n \"assistant_id\": null,\n \"run_id\": null,\n \"metadata\": {}\n }\n ],\n \"first_id\": \"msg_abc123\",\n \"last_id\": \"msg_abc456\",\n \"has_more\": false\n}\n" - } - } - }, - "post": { - "operationId": "createMessage", - "tags": [ - "Assistants" - ], - "summary": "Create a message.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the [thread](/docs/api-reference/threads) to create a message for." - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateMessageRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create message", - "group": "threads", - "beta": true, - "returns": "A [message](/docs/api-reference/messages/object) object.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/messages \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -d '{\n \"role\": \"user\",\n \"content\": \"How does AI work? Explain it in simple terms.\"\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nthread_message = client.beta.threads.messages.create(\n \"thread_abc123\",\n role=\"user\",\n content=\"How does AI work? Explain it in simple terms.\",\n)\nprint(thread_message)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const threadMessages = await openai.beta.threads.messages.create(\n \"thread_abc123\",\n { role: \"user\", content: \"How does AI work? Explain it in simple terms.\" }\n );\n\n console.log(threadMessages);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"msg_abc123\",\n \"object\": \"thread.message\",\n \"created_at\": 1699017614,\n \"thread_id\": \"thread_abc123\",\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": {\n \"value\": \"How does AI work? Explain it in simple terms.\",\n \"annotations\": []\n }\n }\n ],\n \"file_ids\": [],\n \"assistant_id\": null,\n \"run_id\": null,\n \"metadata\": {}\n}\n" - } - } - } - }, - "/threads/{thread_id}/messages/{message_id}": { - "get": { - "operationId": "getMessage", - "tags": [ - "Assistants" - ], - "summary": "Retrieve a message.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the [thread](/docs/api-reference/threads) to which this message belongs." - }, - { - "in": "path", - "name": "message_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the message to retrieve." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve message", - "group": "threads", - "beta": true, - "returns": "The [message](/docs/api-reference/threads/messages/object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/messages/msg_abc123 \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmessage = client.beta.threads.messages.retrieve(\n message_id=\"msg_abc123\",\n thread_id=\"thread_abc123\",\n)\nprint(message)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const message = await openai.beta.threads.messages.retrieve(\n \"thread_abc123\",\n \"msg_abc123\"\n );\n\n console.log(message);\n}\n\nmain();" - }, - "response": "{\n \"id\": \"msg_abc123\",\n \"object\": \"thread.message\",\n \"created_at\": 1699017614,\n \"thread_id\": \"thread_abc123\",\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": {\n \"value\": \"How does AI work? Explain it in simple terms.\",\n \"annotations\": []\n }\n }\n ],\n \"file_ids\": [],\n \"assistant_id\": null,\n \"run_id\": null,\n \"metadata\": {}\n}\n" - } - } - }, - "post": { - "operationId": "modifyMessage", - "tags": [ - "Assistants" - ], - "summary": "Modifies a message.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the thread to which this message belongs." - }, - { - "in": "path", - "name": "message_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the message to modify." - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModifyMessageRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Modify message", - "group": "threads", - "beta": true, - "returns": "The modified [message](/docs/api-reference/threads/messages/object) object.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/messages/msg_abc123 \\\n -H \"Content-Type: application/json\" \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -d '{\n \"metadata\": {\n \"modified\": \"true\",\n \"user\": \"abc123\"\n }\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmessage = client.beta.threads.messages.update(\n message_id=\"msg_abc12\",\n thread_id=\"thread_abc123\",\n metadata={\n \"modified\": \"true\",\n \"user\": \"abc123\",\n },\n)\nprint(message)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const message = await openai.beta.threads.messages.update(\n \"thread_abc123\",\n \"msg_abc123\",\n {\n metadata: {\n modified: \"true\",\n user: \"abc123\",\n },\n }\n }'" - }, - "response": "{\n \"id\": \"msg_abc123\",\n \"object\": \"thread.message\",\n \"created_at\": 1699017614,\n \"thread_id\": \"thread_abc123\",\n \"role\": \"user\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": {\n \"value\": \"How does AI work? Explain it in simple terms.\",\n \"annotations\": []\n }\n }\n ],\n \"file_ids\": [],\n \"assistant_id\": null,\n \"run_id\": null,\n \"metadata\": {\n \"modified\": \"true\",\n \"user\": \"abc123\"\n }\n}\n" - } - } - } - }, - "/threads/runs": { - "post": { - "operationId": "createThreadAndRun", - "tags": [ - "Assistants" - ], - "summary": "Create a thread and run it in one request.", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateThreadAndRunRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RunObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create thread and run", - "group": "threads", - "beta": true, - "returns": "A [run](/docs/api-reference/runs/object) object.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/runs \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -d '{\n \"assistant_id\": \"asst_abc123\",\n \"thread\": {\n \"messages\": [\n {\"role\": \"user\", \"content\": \"Explain deep learning to a 5 year old.\"}\n ]\n }\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nrun = client.beta.threads.create_and_run(\n assistant_id=\"asst_abc123\",\n thread={\n \"messages\": [\n {\"role\": \"user\", \"content\": \"Explain deep learning to a 5 year old.\"}\n ]\n }\n)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const run = await openai.beta.threads.createAndRun({\n assistant_id: \"asst_abc123\",\n thread: {\n messages: [\n { role: \"user\", content: \"Explain deep learning to a 5 year old.\" },\n ],\n },\n });\n\n console.log(run);\n}\n\nmain();\n" - }, - "response": "{\n \"id\": \"run_abc123\",\n \"object\": \"thread.run\",\n \"created_at\": 1699076792,\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"status\": \"queued\",\n \"started_at\": null,\n \"expires_at\": 1699077392,\n \"cancelled_at\": null,\n \"failed_at\": null,\n \"completed_at\": null,\n \"last_error\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You are a helpful assistant.\",\n \"tools\": [],\n \"file_ids\": [],\n \"metadata\": {}\n}\n" - } - } - } - }, - "/threads/{thread_id}/runs": { - "get": { - "operationId": "listRuns", - "tags": [ - "Assistants" - ], - "summary": "Returns a list of runs belonging to a thread.", - "parameters": [ - { - "name": "thread_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the thread the run belongs to." - }, - { - "name": "limit", - "in": "query", - "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20.\n", - "required": false, - "schema": { - "type": "integer", - "default": 20 - } - }, - { - "name": "order", - "in": "query", - "description": "Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order.\n", - "schema": { - "type": "string", - "default": "desc", - "enum": [ - "asc", - "desc" - ] - } - }, - { - "name": "after", - "in": "query", - "description": "A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list.\n", - "schema": { - "type": "string" - } - }, - { - "name": "before", - "in": "query", - "description": "A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list.\n", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListRunsResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List runs", - "group": "threads", - "beta": true, - "returns": "A list of [run](/docs/api-reference/runs/object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/runs \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nruns = client.beta.threads.runs.list(\n \"thread_abc123\"\n)\nprint(runs)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const runs = await openai.beta.threads.runs.list(\n \"thread_abc123\"\n );\n\n console.log(runs);\n}\n\nmain();\n" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"id\": \"run_abc123\",\n \"object\": \"thread.run\",\n \"created_at\": 1699075072,\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"status\": \"completed\",\n \"started_at\": 1699075072,\n \"expires_at\": null,\n \"cancelled_at\": null,\n \"failed_at\": null,\n \"completed_at\": 1699075073,\n \"last_error\": null,\n \"model\": \"gpt-3.5-turbo\",\n \"instructions\": null,\n \"tools\": [\n {\n \"type\": \"code_interpreter\"\n }\n ],\n \"file_ids\": [\n \"file-abc123\",\n \"file-abc456\"\n ],\n \"metadata\": {}\n },\n {\n \"id\": \"run_abc456\",\n \"object\": \"thread.run\",\n \"created_at\": 1699063290,\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"status\": \"completed\",\n \"started_at\": 1699063290,\n \"expires_at\": null,\n \"cancelled_at\": null,\n \"failed_at\": null,\n \"completed_at\": 1699063291,\n \"last_error\": null,\n \"model\": \"gpt-3.5-turbo\",\n \"instructions\": null,\n \"tools\": [\n {\n \"type\": \"code_interpreter\"\n }\n ],\n \"file_ids\": [\n \"file-abc123\",\n \"file-abc456\"\n ],\n \"metadata\": {}\n }\n ],\n \"first_id\": \"run_abc123\",\n \"last_id\": \"run_abc456\",\n \"has_more\": false\n}\n" - } - } - }, - "post": { - "operationId": "createRun", - "tags": [ - "Assistants" - ], - "summary": "Create a run.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the thread to run." - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateRunRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RunObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create run", - "group": "threads", - "beta": true, - "returns": "A [run](/docs/api-reference/runs/object) object.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/runs \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -d '{\n \"assistant_id\": \"asst_abc123\"\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nrun = client.beta.threads.runs.create(\n thread_id=\"thread_abc123\",\n assistant_id=\"asst_abc123\"\n)\nprint(run)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const run = await openai.beta.threads.runs.create(\n \"thread_abc123\",\n { assistant_id: \"asst_abc123\" }\n );\n\n console.log(run);\n}\n\nmain();\n" - }, - "response": "{\n \"id\": \"run_abc123\",\n \"object\": \"thread.run\",\n \"created_at\": 1699063290,\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"status\": \"queued\",\n \"started_at\": 1699063290,\n \"expires_at\": null,\n \"cancelled_at\": null,\n \"failed_at\": null,\n \"completed_at\": 1699063291,\n \"last_error\": null,\n \"model\": \"gpt-4\",\n \"instructions\": null,\n \"tools\": [\n {\n \"type\": \"code_interpreter\"\n }\n ],\n \"file_ids\": [\n \"file-abc123\",\n \"file-abc456\"\n ],\n \"metadata\": {}\n}\n" - } - } - } - }, - "/threads/{thread_id}/runs/{run_id}": { - "get": { - "operationId": "getRun", - "tags": [ - "Assistants" - ], - "summary": "Retrieves a run.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the [thread](/docs/api-reference/threads) that was run." - }, - { - "in": "path", - "name": "run_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the run to retrieve." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RunObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve run", - "group": "threads", - "beta": true, - "returns": "The [run](/docs/api-reference/runs/object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123 \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nrun = client.beta.threads.runs.retrieve(\n thread_id=\"thread_abc123\",\n run_id=\"run_abc123\"\n)\nprint(run)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const run = await openai.beta.threads.runs.retrieve(\n \"thread_abc123\",\n \"run_abc123\"\n );\n\n console.log(run);\n}\n\nmain();\n" - }, - "response": "{\n \"id\": \"run_abc123\",\n \"object\": \"thread.run\",\n \"created_at\": 1699075072,\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"status\": \"completed\",\n \"started_at\": 1699075072,\n \"expires_at\": null,\n \"cancelled_at\": null,\n \"failed_at\": null,\n \"completed_at\": 1699075073,\n \"last_error\": null,\n \"model\": \"gpt-3.5-turbo\",\n \"instructions\": null,\n \"tools\": [\n {\n \"type\": \"code_interpreter\"\n }\n ],\n \"file_ids\": [\n \"file-abc123\",\n \"file-abc456\"\n ],\n \"metadata\": {}\n}\n" - } - } - }, - "post": { - "operationId": "modifyRun", - "tags": [ - "Assistants" - ], - "summary": "Modifies a run.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the [thread](/docs/api-reference/threads) that was run." - }, - { - "in": "path", - "name": "run_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the run to modify." - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModifyRunRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RunObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Modify run", - "group": "threads", - "beta": true, - "returns": "The modified [run](/docs/api-reference/runs/object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123 \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -d '{\n \"metadata\": {\n \"user_id\": \"user_abc123\"\n }\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nrun = client.beta.threads.runs.update(\n thread_id=\"thread_abc123\",\n run_id=\"run_abc123\",\n metadata={\"user_id\": \"user_abc123\"},\n)\nprint(run)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const run = await openai.beta.threads.runs.update(\n \"thread_abc123\",\n \"run_abc123\",\n {\n metadata: {\n user_id: \"user_abc123\",\n },\n }\n );\n\n console.log(run);\n}\n\nmain();\n" - }, - "response": "{\n \"id\": \"run_abc123\",\n \"object\": \"thread.run\",\n \"created_at\": 1699075072,\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"status\": \"completed\",\n \"started_at\": 1699075072,\n \"expires_at\": null,\n \"cancelled_at\": null,\n \"failed_at\": null,\n \"completed_at\": 1699075073,\n \"last_error\": null,\n \"model\": \"gpt-3.5-turbo\",\n \"instructions\": null,\n \"tools\": [\n {\n \"type\": \"code_interpreter\"\n }\n ],\n \"file_ids\": [\n \"file-abc123\",\n \"file-abc456\"\n ],\n \"metadata\": {\n \"user_id\": \"user_abc123\"\n }\n}\n" - } - } - } - }, - "/threads/{thread_id}/runs/{run_id}/submit_tool_outputs": { - "post": { - "operationId": "submitToolOuputsToRun", - "tags": [ - "Assistants" - ], - "summary": "When a run has the `status: \"requires_action\"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request.\n", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the [thread](/docs/api-reference/threads) to which this run belongs." - }, - { - "in": "path", - "name": "run_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the run that requires the tool output submission." - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SubmitToolOutputsRunRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RunObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Submit tool outputs to run", - "group": "threads", - "beta": true, - "returns": "The modified [run](/docs/api-reference/runs/object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123/submit_tool_outputs \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -d '{\n \"tool_outputs\": [\n {\n \"tool_call_id\": \"call_abc123\",\n \"output\": \"28C\"\n }\n ]\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nrun = client.beta.threads.runs.submit_tool_outputs(\n thread_id=\"thread_abc123\",\n run_id=\"run_abc123\",\n tool_outputs=[\n {\n \"tool_call_id\": \"call_abc123\",\n \"output\": \"28C\"\n }\n ]\n)\nprint(run)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const run = await openai.beta.threads.runs.submitToolOutputs(\n \"thread_abc123\",\n \"run_abc123\",\n {\n tool_outputs: [\n {\n tool_call_id: \"call_abc123\",\n output: \"28C\",\n },\n ],\n }\n );\n\n console.log(run);\n}\n\nmain();\n" - }, - "response": "{\n \"id\": \"run_abc123\",\n \"object\": \"thread.run\",\n \"created_at\": 1699075592,\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"status\": \"queued\",\n \"started_at\": 1699075592,\n \"expires_at\": 1699076192,\n \"cancelled_at\": null,\n \"failed_at\": null,\n \"completed_at\": null,\n \"last_error\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You tell the weather.\",\n \"tools\": [\n {\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_weather\",\n \"description\": \"Determine weather in my location\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"location\": {\n \"type\": \"string\",\n \"description\": \"The city and state e.g. San Francisco, CA\"\n },\n \"unit\": {\n \"type\": \"string\",\n \"enum\": [\n \"c\",\n \"f\"\n ]\n }\n },\n \"required\": [\n \"location\"\n ]\n }\n }\n }\n ],\n \"file_ids\": [],\n \"metadata\": {}\n}\n" - } - } - } - }, - "/threads/{thread_id}/runs/{run_id}/cancel": { - "post": { - "operationId": "cancelRun", - "tags": [ - "Assistants" - ], - "summary": "Cancels a run that is `in_progress`.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the thread to which this run belongs." - }, - { - "in": "path", - "name": "run_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the run to cancel." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RunObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Cancel a run", - "group": "threads", - "beta": true, - "returns": "The modified [run](/docs/api-reference/runs/object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123/cancel \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -X POST\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nrun = client.beta.threads.runs.cancel(\n thread_id=\"thread_abc123\",\n run_id=\"run_abc123\"\n)\nprint(run)\n", - "node.js": "import OpenAI from \"openai\";\n\nconst openai = new OpenAI();\n\nasync function main() {\n const run = await openai.beta.threads.runs.cancel(\n \"thread_abc123\",\n \"run_abc123\"\n );\n\n console.log(run);\n}\n\nmain();\n" - }, - "response": "{\n \"id\": \"run_abc123\",\n \"object\": \"thread.run\",\n \"created_at\": 1699076126,\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"status\": \"cancelling\",\n \"started_at\": 1699076126,\n \"expires_at\": 1699076726,\n \"cancelled_at\": null,\n \"failed_at\": null,\n \"completed_at\": null,\n \"last_error\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You summarize books.\",\n \"tools\": [\n {\n \"type\": \"retrieval\"\n }\n ],\n \"file_ids\": [],\n \"metadata\": {}\n}\n" - } - } - } - }, - "/threads/{thread_id}/runs/{run_id}/steps": { - "get": { - "operationId": "listRunSteps", - "tags": [ - "Assistants" - ], - "summary": "Returns a list of run steps belonging to a run.", - "parameters": [ - { - "name": "thread_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the thread the run and run steps belong to." - }, - { - "name": "run_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the run the run steps belong to." - }, - { - "name": "limit", - "in": "query", - "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20.\n", - "required": false, - "schema": { - "type": "integer", - "default": 20 - } - }, - { - "name": "order", - "in": "query", - "description": "Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order.\n", - "schema": { - "type": "string", - "default": "desc", - "enum": [ - "asc", - "desc" - ] - } - }, - { - "name": "after", - "in": "query", - "description": "A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list.\n", - "schema": { - "type": "string" - } - }, - { - "name": "before", - "in": "query", - "description": "A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list.\n", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListRunStepsResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List run steps", - "group": "threads", - "beta": true, - "returns": "A list of [run step](/docs/api-reference/runs/step-object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123/steps \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nrun_steps = client.beta.threads.runs.steps.list(\n thread_id=\"thread_abc123\",\n run_id=\"run_abc123\"\n)\nprint(run_steps)\n", - "node.js": "import OpenAI from \"openai\";\nconst openai = new OpenAI();\n\nasync function main() {\n const runStep = await openai.beta.threads.runs.steps.list(\n \"thread_abc123\",\n \"run_abc123\"\n );\n console.log(runStep);\n}\n\nmain();\n" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"id\": \"step_abc123\",\n \"object\": \"thread.run.step\",\n \"created_at\": 1699063291,\n \"run_id\": \"run_abc123\",\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"type\": \"message_creation\",\n \"status\": \"completed\",\n \"cancelled_at\": null,\n \"completed_at\": 1699063291,\n \"expired_at\": null,\n \"failed_at\": null,\n \"last_error\": null,\n \"step_details\": {\n \"type\": \"message_creation\",\n \"message_creation\": {\n \"message_id\": \"msg_abc123\"\n }\n }\n }\n ],\n \"first_id\": \"step_abc123\",\n \"last_id\": \"step_abc456\",\n \"has_more\": false\n}\n" - } - } - } - }, - "/threads/{thread_id}/runs/{run_id}/steps/{step_id}": { - "get": { - "operationId": "getRunStep", - "tags": [ - "Assistants" - ], - "summary": "Retrieves a run step.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the thread to which the run and run step belongs." - }, - { - "in": "path", - "name": "run_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the run to which the run step belongs." - }, - { - "in": "path", - "name": "step_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the run step to retrieve." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RunStepObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve run step", - "group": "threads", - "beta": true, - "returns": "The [run step](/docs/api-reference/runs/step-object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123/steps/step_abc123 \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nrun_step = client.beta.threads.runs.steps.retrieve(\n thread_id=\"thread_abc123\",\n run_id=\"run_abc123\",\n step_id=\"step_abc123\"\n)\nprint(run_step)\n", - "node.js": "import OpenAI from \"openai\";\nconst openai = new OpenAI();\n\nasync function main() {\n const runStep = await openai.beta.threads.runs.steps.retrieve(\n \"thread_abc123\",\n \"run_abc123\",\n \"step_abc123\"\n );\n console.log(runStep);\n}\n\nmain();\n" - }, - "response": "{\n \"id\": \"step_abc123\",\n \"object\": \"thread.run.step\",\n \"created_at\": 1699063291,\n \"run_id\": \"run_abc123\",\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"type\": \"message_creation\",\n \"status\": \"completed\",\n \"cancelled_at\": null,\n \"completed_at\": 1699063291,\n \"expired_at\": null,\n \"failed_at\": null,\n \"last_error\": null,\n \"step_details\": {\n \"type\": \"message_creation\",\n \"message_creation\": {\n \"message_id\": \"msg_abc123\"\n }\n }\n}\n" - } - } - } - }, - "/assistants/{assistant_id}/files": { - "get": { - "operationId": "listAssistantFiles", - "tags": [ - "Assistants" - ], - "summary": "Returns a list of assistant files.", - "parameters": [ - { - "name": "assistant_id", - "in": "path", - "description": "The ID of the assistant the file belongs to.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20.\n", - "required": false, - "schema": { - "type": "integer", - "default": 20 - } - }, - { - "name": "order", - "in": "query", - "description": "Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order.\n", - "schema": { - "type": "string", - "default": "desc", - "enum": [ - "asc", - "desc" - ] - } - }, - { - "name": "after", - "in": "query", - "description": "A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list.\n", - "schema": { - "type": "string" - } - }, - { - "name": "before", - "in": "query", - "description": "A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list.\n", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListAssistantFilesResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List assistant files", - "group": "assistants", - "beta": true, - "returns": "A list of [assistant file](/docs/api-reference/assistants/file-object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/assistants/asst_abc123/files \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nassistant_files = client.beta.assistants.files.list(\n assistant_id=\"asst_abc123\"\n)\nprint(assistant_files)\n", - "node.js": "import OpenAI from \"openai\";\nconst openai = new OpenAI();\n\nasync function main() {\n const assistantFiles = await openai.beta.assistants.files.list(\n \"asst_abc123\"\n );\n console.log(assistantFiles);\n}\n\nmain();\n" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"id\": \"file-abc123\",\n \"object\": \"assistant.file\",\n \"created_at\": 1699060412,\n \"assistant_id\": \"asst_abc123\"\n },\n {\n \"id\": \"file-abc456\",\n \"object\": \"assistant.file\",\n \"created_at\": 1699060412,\n \"assistant_id\": \"asst_abc123\"\n }\n ],\n \"first_id\": \"file-abc123\",\n \"last_id\": \"file-abc456\",\n \"has_more\": false\n}\n" - } - } - }, - "post": { - "operationId": "createAssistantFile", - "tags": [ - "Assistants" - ], - "summary": "Create an assistant file by attaching a [File](/docs/api-reference/files) to an [assistant](/docs/api-reference/assistants).", - "parameters": [ - { - "in": "path", - "name": "assistant_id", - "required": true, - "schema": { - "type": "string", - "example": "file-abc123" - }, - "description": "The ID of the assistant for which to create a File.\n" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateAssistantFileRequest" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AssistantFileObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Create assistant file", - "group": "assistants", - "beta": true, - "returns": "An [assistant file](/docs/api-reference/assistants/file-object) object.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/assistants/asst_abc123/files \\\n -H 'Authorization: Bearer $OPENAI_API_KEY\"' \\\n -H 'Content-Type: application/json' \\\n -H 'OpenAI-Beta: assistants=v1' \\\n -d '{\n \"file_id\": \"file-abc123\"\n }'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nassistant_file = client.beta.assistants.files.create(\n assistant_id=\"asst_abc123\",\n file_id=\"file-abc123\"\n)\nprint(assistant_file)\n", - "node.js": "import OpenAI from \"openai\";\nconst openai = new OpenAI();\n\nasync function main() {\n const myAssistantFile = await openai.beta.assistants.files.create(\n \"asst_abc123\",\n {\n file_id: \"file-abc123\"\n }\n );\n console.log(myAssistantFile);\n}\n\nmain();\n" - }, - "response": "{\n \"id\": \"file-abc123\",\n \"object\": \"assistant.file\",\n \"created_at\": 1699055364,\n \"assistant_id\": \"asst_abc123\"\n}\n" - } - } - } - }, - "/assistants/{assistant_id}/files/{file_id}": { - "get": { - "operationId": "getAssistantFile", - "tags": [ - "Assistants" - ], - "summary": "Retrieves an AssistantFile.", - "parameters": [ - { - "in": "path", - "name": "assistant_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the assistant who the file belongs to." - }, - { - "in": "path", - "name": "file_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the file we're getting." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AssistantFileObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve assistant file", - "group": "assistants", - "beta": true, - "returns": "The [assistant file](/docs/api-reference/assistants/file-object) object matching the specified ID.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/assistants/asst_abc123/files/file-abc123 \\\n -H 'Authorization: Bearer $OPENAI_API_KEY\"' \\\n -H 'Content-Type: application/json' \\\n -H 'OpenAI-Beta: assistants=v1'\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nassistant_file = client.beta.assistants.files.retrieve(\n assistant_id=\"asst_abc123\",\n file_id=\"file-abc123\"\n)\nprint(assistant_file)\n", - "node.js": "import OpenAI from \"openai\";\nconst openai = new OpenAI();\n\nasync function main() {\n const myAssistantFile = await openai.beta.assistants.files.retrieve(\n \"asst_abc123\",\n \"file-abc123\"\n );\n console.log(myAssistantFile);\n}\n\nmain();\n" - }, - "response": "{\n \"id\": \"file-abc123\",\n \"object\": \"assistant.file\",\n \"created_at\": 1699055364,\n \"assistant_id\": \"asst_abc123\"\n}\n" - } - } - }, - "delete": { - "operationId": "deleteAssistantFile", - "tags": [ - "Assistants" - ], - "summary": "Delete an assistant file.", - "parameters": [ - { - "in": "path", - "name": "assistant_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the assistant that the file belongs to." - }, - { - "in": "path", - "name": "file_id", - "required": true, - "schema": { - "type": "string" - }, - "description": "The ID of the file to delete." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteAssistantFileResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Delete assistant file", - "group": "assistants", - "beta": true, - "returns": "Deletion status", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/assistants/asst_abc123/files/file-abc123 \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"OpenAI-Beta: assistants=v1\" \\\n -X DELETE\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\ndeleted_assistant_file = client.beta.assistants.files.delete(\n assistant_id=\"asst_abc123\",\n file_id=\"file-abc123\"\n)\nprint(deleted_assistant_file)\n", - "node.js": "import OpenAI from \"openai\";\nconst openai = new OpenAI();\n\nasync function main() {\n const deletedAssistantFile = await openai.beta.assistants.files.del(\n \"asst_abc123\",\n \"file-abc123\"\n );\n console.log(deletedAssistantFile);\n}\n\nmain();\n" - }, - "response": "{\n id: \"file-abc123\",\n object: \"assistant.file.deleted\",\n deleted: true\n}\n" - } - } - } - }, - "/threads/{thread_id}/messages/{message_id}/files": { - "get": { - "operationId": "listMessageFiles", - "tags": [ - "Assistants" - ], - "summary": "Returns a list of message files.", - "parameters": [ - { - "name": "thread_id", - "in": "path", - "description": "The ID of the thread that the message and files belong to.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "message_id", - "in": "path", - "description": "The ID of the message that the files belongs to.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20.\n", - "required": false, - "schema": { - "type": "integer", - "default": 20 - } - }, - { - "name": "order", - "in": "query", - "description": "Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order.\n", - "schema": { - "type": "string", - "default": "desc", - "enum": [ - "asc", - "desc" - ] - } - }, - { - "name": "after", - "in": "query", - "description": "A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list.\n", - "schema": { - "type": "string" - } - }, - { - "name": "before", - "in": "query", - "description": "A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list.\n", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListMessageFilesResponse" - } - } - } - } - }, - "x-oaiMeta": { - "name": "List message files", - "group": "threads", - "beta": true, - "returns": "A list of [message file](/docs/api-reference/messages/file-object) objects.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/messages/msg_abc123/files \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmessage_files = client.beta.threads.messages.files.list(\n thread_id=\"thread_abc123\",\n message_id=\"msg_abc123\"\n)\nprint(message_files)\n", - "node.js": "import OpenAI from \"openai\";\nconst openai = new OpenAI();\n\nasync function main() {\n const messageFiles = await openai.beta.threads.messages.files.list(\n \"thread_abc123\",\n \"msg_abc123\"\n );\n console.log(messageFiles);\n}\n\nmain();\n" - }, - "response": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"id\": \"file-abc123\",\n \"object\": \"thread.message.file\",\n \"created_at\": 1699061776,\n \"message_id\": \"msg_abc123\"\n },\n {\n \"id\": \"file-abc123\",\n \"object\": \"thread.message.file\",\n \"created_at\": 1699061776,\n \"message_id\": \"msg_abc123\"\n }\n ],\n \"first_id\": \"file-abc123\",\n \"last_id\": \"file-abc123\",\n \"has_more\": false\n}\n" - } - } - } - }, - "/threads/{thread_id}/messages/{message_id}/files/{file_id}": { - "get": { - "operationId": "getMessageFile", - "tags": [ - "Assistants" - ], - "summary": "Retrieves a message file.", - "parameters": [ - { - "in": "path", - "name": "thread_id", - "required": true, - "schema": { - "type": "string", - "example": "thread_abc123" - }, - "description": "The ID of the thread to which the message and File belong." - }, - { - "in": "path", - "name": "message_id", - "required": true, - "schema": { - "type": "string", - "example": "msg_abc123" - }, - "description": "The ID of the message the file belongs to." - }, - { - "in": "path", - "name": "file_id", - "required": true, - "schema": { - "type": "string", - "example": "file-abc123" - }, - "description": "The ID of the file being retrieved." - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageFileObject" - } - } - } - } - }, - "x-oaiMeta": { - "name": "Retrieve message file", - "group": "threads", - "beta": true, - "returns": "The [message file](/docs/api-reference/messages/file-object) object.", - "examples": { - "request": { - "curl": "curl https://api.openai.com/v1/threads/thread_abc123/messages/msg_abc123/files/file-abc123 \\\n -H \"Authorization: Bearer $OPENAI_API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -H \"OpenAI-Beta: assistants=v1\"\n", - "python": "from openai import OpenAI\nclient = OpenAI()\n\nmessage_files = client.beta.threads.messages.files.retrieve(\n thread_id=\"thread_abc123\",\n message_id=\"msg_abc123\",\n file_id=\"file-abc123\"\n)\nprint(message_files)\n", - "node.js": "import OpenAI from \"openai\";\nconst openai = new OpenAI();\n\nasync function main() {\n const messageFile = await openai.beta.threads.messages.files.retrieve(\n \"thread_abc123\",\n \"msg_abc123\",\n \"file-abc123\"\n );\n console.log(messageFile);\n}\n\nmain();\n" - }, - "response": "{\n \"id\": \"file-abc123\",\n \"object\": \"thread.message.file\",\n \"created_at\": 1699061776,\n \"message_id\": \"msg_abc123\"\n}\n" - } - } - } - } - }, - "components": { - "securitySchemes": { - "ApiKeyAuth": { - "type": "http", - "scheme": "bearer" - } - }, - "schemas": { - "Error": { - "type": "object", - "properties": { - "code": { - "type": "string", - "nullable": true - }, - "message": { - "type": "string", - "nullable": false - }, - "param": { - "type": "string", - "nullable": true - }, - "type": { - "type": "string", - "nullable": false - } - }, - "required": [ - "type", - "message", - "param", - "code" - ] - }, - "ErrorResponse": { - "type": "object", - "properties": { - "error": { - "$ref": "#/components/schemas/Error" - } - }, - "required": [ - "error" - ] - }, - "ListModelsResponse": { - "type": "object", - "properties": { - "object": { - "type": "string", - "enum": [ - "list" - ] - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Model" - } - } - }, - "required": [ - "object", - "data" - ] - }, - "DeleteModelResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "deleted": { - "type": "boolean" - }, - "object": { - "type": "string" - } - }, - "required": [ - "id", - "object", - "deleted" - ] - }, - "CreateCompletionRequest": { - "type": "object", - "properties": { - "model": { - "description": "ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them.\n", - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "babbage-002", - "davinci-002", - "gpt-3.5-turbo-instruct", - "text-davinci-003", - "text-davinci-002", - "text-davinci-001", - "code-davinci-002", - "text-curie-001", - "text-babbage-001", - "text-ada-001" - ] - } - ], - "x-oaiTypeLabel": "string" - }, - "prompt": { - "description": "The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays.\n\nNote that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document.\n", - "default": "<|endoftext|>", - "nullable": true, - "oneOf": [ - { - "type": "string", - "default": "", - "example": "This is a test." - }, - { - "type": "array", - "items": { - "type": "string", - "default": "", - "example": "This is a test." - } - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "integer" - }, - "example": "[1212, 318, 257, 1332, 13]" - }, - { - "type": "array", - "minItems": 1, - "items": { - "type": "array", - "minItems": 1, - "items": { - "type": "integer" - } - }, - "example": "[[1212, 318, 257, 1332, 13]]" - } - ] - }, - "best_of": { - "type": "integer", - "default": 1, - "minimum": 0, - "maximum": 20, - "nullable": true, - "description": "Generates `best_of` completions server-side and returns the \"best\" (the one with the highest log probability per token). Results cannot be streamed.\n\nWhen used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`.\n\n**Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`.\n" - }, - "echo": { - "type": "boolean", - "default": false, - "nullable": true, - "description": "Echo back the prompt in addition to the completion\n" - }, - "frequency_penalty": { - "type": "number", - "default": 0, - "minimum": -2, - "maximum": 2, - "nullable": true, - "description": "Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.\n\n[See more information about frequency and presence penalties.](/docs/guides/text-generation/parameter-details)\n" - }, - "logit_bias": { - "type": "object", - "x-oaiTypeLabel": "map", - "default": null, - "nullable": true, - "additionalProperties": { - "type": "integer" - }, - "description": "Modify the likelihood of specified tokens appearing in the completion.\n\nAccepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) (which works for both GPT-2 and GPT-3) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.\n\nAs an example, you can pass `{\"50256\": -100}` to prevent the <|endoftext|> token from being generated.\n" - }, - "logprobs": { - "type": "integer", - "minimum": 0, - "maximum": 5, - "default": null, - "nullable": true, - "description": "Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response.\n\nThe maximum value for `logprobs` is 5.\n" - }, - "max_tokens": { - "type": "integer", - "minimum": 0, - "default": 16, - "example": 16, - "nullable": true, - "description": "The maximum number of [tokens](/tokenizer) that can be generated in the completion.\n\nThe token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens.\n" - }, - "n": { - "type": "integer", - "minimum": 1, - "maximum": 128, - "default": 1, - "example": 1, - "nullable": true, - "description": "How many completions to generate for each prompt.\n\n**Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`.\n" - }, - "presence_penalty": { - "type": "number", - "default": 0, - "minimum": -2, - "maximum": 2, - "nullable": true, - "description": "Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.\n\n[See more information about frequency and presence penalties.](/docs/guides/text-generation/parameter-details)\n" - }, - "seed": { - "type": "integer", - "minimum": -9223372036854776000, - "maximum": 9223372036854776000, - "nullable": true, - "description": "If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result.\n\nDeterminism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend.\n" - }, - "stop": { - "description": "Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.\n", - "default": null, - "nullable": true, - "oneOf": [ - { - "type": "string", - "default": "<|endoftext|>", - "example": "\n", - "nullable": true - }, - { - "type": "array", - "minItems": 1, - "maxItems": 4, - "items": { - "type": "string", - "example": "[\"\\n\"]" - } - } - ] - }, - "stream": { - "description": "Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions).\n", - "type": "boolean", - "nullable": true, - "default": false - }, - "suffix": { - "description": "The suffix that comes after a completion of inserted text.", - "default": null, - "nullable": true, - "type": "string", - "example": "test." - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2, - "default": 1, - "example": 1, - "nullable": true, - "description": "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n\nWe generally recommend altering this or `top_p` but not both.\n" - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1, - "default": 1, - "example": 1, - "nullable": true, - "description": "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }, - "user": { - "type": "string", - "example": "user-1234", - "description": "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\n" - } - }, - "required": [ - "model", - "prompt" - ] - }, - "CreateCompletionResponse": { - "type": "object", - "description": "Represents a completion response from the API. Note: both the streamed and non-streamed response objects share the same shape (unlike the chat endpoint).\n", - "properties": { - "id": { - "type": "string", - "description": "A unique identifier for the completion." - }, - "choices": { - "type": "array", - "description": "The list of completion choices the model generated for the input prompt.", - "items": { - "type": "object", - "required": [ - "finish_reason", - "index", - "logprobs", - "text" - ], - "properties": { - "finish_reason": { - "type": "string", - "description": "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence,\n`length` if the maximum number of tokens specified in the request was reached,\nor `content_filter` if content was omitted due to a flag from our content filters.\n", - "enum": [ - "stop", - "length", - "content_filter" - ] - }, - "index": { - "type": "integer" - }, - "logprobs": { - "type": "object", - "nullable": true, - "properties": { - "text_offset": { - "type": "array", - "items": { - "type": "integer" - } - }, - "token_logprobs": { - "type": "array", - "items": { - "type": "number" - } - }, - "tokens": { - "type": "array", - "items": { - "type": "string" - } - }, - "top_logprobs": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": { - "type": "number" - } - } - } - } - }, - "text": { - "type": "string" - } - } - } - }, - "created": { - "type": "integer", - "description": "The Unix timestamp (in seconds) of when the completion was created." - }, - "model": { - "type": "string", - "description": "The model used for completion." - }, - "system_fingerprint": { - "type": "string", - "description": "This fingerprint represents the backend configuration that the model runs with.\n\nCan be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.\n" - }, - "object": { - "type": "string", - "description": "The object type, which is always \"text_completion\"", - "enum": [ - "text_completion" - ] - }, - "usage": { - "$ref": "#/components/schemas/CompletionUsage" - } - }, - "required": [ - "id", - "object", - "created", - "model", - "choices" - ], - "x-oaiMeta": { - "name": "The completion object", - "legacy": true, - "example": "{\n \"id\": \"cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7\",\n \"object\": \"text_completion\",\n \"created\": 1589478378,\n \"model\": \"gpt-3.5-turbo\",\n \"choices\": [\n {\n \"text\": \"\\n\\nThis is indeed a test\",\n \"index\": 0,\n \"logprobs\": null,\n \"finish_reason\": \"length\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\": 5,\n \"completion_tokens\": 7,\n \"total_tokens\": 12\n }\n}\n" - } - }, - "ChatCompletionRequestMessageContentPart": { - "oneOf": [ - { - "$ref": "#/components/schemas/ChatCompletionRequestMessageContentPartText" - }, - { - "$ref": "#/components/schemas/ChatCompletionRequestMessageContentPartImage" - } - ], - "x-oaiExpandable": true - }, - "ChatCompletionRequestMessageContentPartImage": { - "type": "object", - "title": "Image content part", - "properties": { - "type": { - "type": "string", - "enum": [ - "image_url" - ], - "description": "The type of the content part." - }, - "image_url": { - "type": "object", - "properties": { - "url": { - "type": "string", - "description": "Either a URL of the image or the base64 encoded image data.", - "format": "uri" - }, - "detail": { - "type": "string", - "description": "Specifies the detail level of the image. Learn more in the [Vision guide](/docs/guides/vision/low-or-high-fidelity-image-understanding).", - "enum": [ - "auto", - "low", - "high" - ], - "default": "auto" - } - }, - "required": [ - "url" - ] - } - }, - "required": [ - "type", - "image_url" - ] - }, - "ChatCompletionRequestMessageContentPartText": { - "type": "object", - "title": "Text content part", - "properties": { - "type": { - "type": "string", - "enum": [ - "text" - ], - "description": "The type of the content part." - }, - "text": { - "type": "string", - "description": "The text content." - } - }, - "required": [ - "type", - "text" - ] - }, - "ChatCompletionRequestMessage": { - "oneOf": [ - { - "$ref": "#/components/schemas/ChatCompletionRequestSystemMessage" - }, - { - "$ref": "#/components/schemas/ChatCompletionRequestUserMessage" - }, - { - "$ref": "#/components/schemas/ChatCompletionRequestAssistantMessage" - }, - { - "$ref": "#/components/schemas/ChatCompletionRequestToolMessage" - }, - { - "$ref": "#/components/schemas/ChatCompletionRequestFunctionMessage" - } - ], - "x-oaiExpandable": true - }, - "ChatCompletionRequestSystemMessage": { - "type": "object", - "title": "System message", - "properties": { - "content": { - "description": "The contents of the system message.", - "type": "string" - }, - "role": { - "type": "string", - "enum": [ - "system" - ], - "description": "The role of the messages author, in this case `system`." - }, - "name": { - "type": "string", - "description": "An optional name for the participant. Provides the model information to differentiate between participants of the same role." - } - }, - "required": [ - "content", - "role" - ] - }, - "ChatCompletionRequestUserMessage": { - "type": "object", - "title": "User message", - "properties": { - "content": { - "description": "The contents of the user message.\n", - "oneOf": [ - { - "type": "string", - "description": "The text contents of the message.", - "title": "Text content" - }, - { - "type": "array", - "description": "An array of content parts with a defined type, each can be of type `text` or `image_url` when passing in images. You can pass multiple images by adding multiple `image_url` content parts. Image input is only supported when using the `gpt-4-visual-preview` model.", - "title": "Array of content parts", - "items": { - "$ref": "#/components/schemas/ChatCompletionRequestMessageContentPart" - }, - "minItems": 1 - } - ], - "x-oaiExpandable": true - }, - "role": { - "type": "string", - "enum": [ - "user" - ], - "description": "The role of the messages author, in this case `user`." - }, - "name": { - "type": "string", - "description": "An optional name for the participant. Provides the model information to differentiate between participants of the same role." - } - }, - "required": [ - "content", - "role" - ] - }, - "ChatCompletionRequestAssistantMessage": { - "type": "object", - "title": "Assistant message", - "properties": { - "content": { - "nullable": true, - "type": "string", - "description": "The contents of the assistant message. Required unless `tool_calls` or `function_call` is specified.\n" - }, - "role": { - "type": "string", - "enum": [ - "assistant" - ], - "description": "The role of the messages author, in this case `assistant`." - }, - "name": { - "type": "string", - "description": "An optional name for the participant. Provides the model information to differentiate between participants of the same role." - }, - "tool_calls": { - "$ref": "#/components/schemas/ChatCompletionMessageToolCalls" - }, - "function_call": { - "type": "object", - "deprecated": true, - "description": "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model.", - "properties": { - "arguments": { - "type": "string", - "description": "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." - }, - "name": { - "type": "string", - "description": "The name of the function to call." - } - }, - "required": [ - "arguments", - "name" - ] - } - }, - "required": [ - "role" - ] - }, - "ChatCompletionRequestToolMessage": { - "type": "object", - "title": "Tool message", - "properties": { - "role": { - "type": "string", - "enum": [ - "tool" - ], - "description": "The role of the messages author, in this case `tool`." - }, - "content": { - "type": "string", - "description": "The contents of the tool message." - }, - "tool_call_id": { - "type": "string", - "description": "Tool call that this message is responding to." - } - }, - "required": [ - "role", - "content", - "tool_call_id" - ] - }, - "ChatCompletionRequestFunctionMessage": { - "type": "object", - "title": "Function message", - "deprecated": true, - "properties": { - "role": { - "type": "string", - "enum": [ - "function" - ], - "description": "The role of the messages author, in this case `function`." - }, - "content": { - "nullable": true, - "type": "string", - "description": "The contents of the function message." - }, - "name": { - "type": "string", - "description": "The name of the function to call." - } - }, - "required": [ - "role", - "content", - "name" - ] - }, - "FunctionParameters": { - "type": "object", - "description": "The parameters the functions accepts, described as a JSON Schema object. See the [guide](/docs/guides/text-generation/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation about the format. \n\nOmitting `parameters` defines a function with an empty parameter list.", - "additionalProperties": true - }, - "ChatCompletionFunctions": { - "type": "object", - "deprecated": true, - "properties": { - "description": { - "type": "string", - "description": "A description of what the function does, used by the model to choose when and how to call the function." - }, - "name": { - "type": "string", - "description": "The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64." - }, - "parameters": { - "$ref": "#/components/schemas/FunctionParameters" - } - }, - "required": [ - "name" - ] - }, - "ChatCompletionFunctionCallOption": { - "type": "object", - "description": "Specifying a particular function via `{\"name\": \"my_function\"}` forces the model to call that function.\n", - "properties": { - "name": { - "type": "string", - "description": "The name of the function to call." - } - }, - "required": [ - "name" - ] - }, - "ChatCompletionTool": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "function" - ], - "description": "The type of the tool. Currently, only `function` is supported." - }, - "function": { - "$ref": "#/components/schemas/FunctionObject" - } - }, - "required": [ - "type", - "function" - ] - }, - "FunctionObject": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "A description of what the function does, used by the model to choose when and how to call the function." - }, - "name": { - "type": "string", - "description": "The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64." - }, - "parameters": { - "$ref": "#/components/schemas/FunctionParameters" - } - }, - "required": [ - "name" - ] - }, - "ChatCompletionToolChoiceOption": { - "description": "Controls which (if any) function is called by the model.\n`none` means the model will not call a function and instead generates a message.\n`auto` means the model can pick between generating a message or calling a function.\nSpecifying a particular function via `{\"type: \"function\", \"function\": {\"name\": \"my_function\"}}` forces the model to call that function.\n\n`none` is the default when no functions are present. `auto` is the default if functions are present.\n", - "oneOf": [ - { - "type": "string", - "description": "`none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function.\n", - "enum": [ - "none", - "auto" - ] - }, - { - "$ref": "#/components/schemas/ChatCompletionNamedToolChoice" - } - ], - "x-oaiExpandable": true - }, - "ChatCompletionNamedToolChoice": { - "type": "object", - "description": "Specifies a tool the model should use. Use to force the model to call a specific function.", - "properties": { - "type": { - "type": "string", - "enum": [ - "function" - ], - "description": "The type of the tool. Currently, only `function` is supported." - }, - "function": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "The name of the function to call." - } - }, - "required": [ - "name" - ] - } - }, - "required": [ - "type", - "function" - ] - }, - "ChatCompletionMessageToolCalls": { - "type": "array", - "description": "The tool calls generated by the model, such as function calls.", - "items": { - "$ref": "#/components/schemas/ChatCompletionMessageToolCall" - } - }, - "ChatCompletionMessageToolCall": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "The ID of the tool call." - }, - "type": { - "type": "string", - "enum": [ - "function" - ], - "description": "The type of the tool. Currently, only `function` is supported." - }, - "function": { - "type": "object", - "description": "The function that the model called.", - "properties": { - "name": { - "type": "string", - "description": "The name of the function to call." - }, - "arguments": { - "type": "string", - "description": "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." - } - }, - "required": [ - "name", - "arguments" - ] - } - }, - "required": [ - "id", - "type", - "function" - ] - }, - "ChatCompletionMessageToolCallChunk": { - "type": "object", - "properties": { - "index": { - "type": "integer" - }, - "id": { - "type": "string", - "description": "The ID of the tool call." - }, - "type": { - "type": "string", - "enum": [ - "function" - ], - "description": "The type of the tool. Currently, only `function` is supported." - }, - "function": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "The name of the function to call." - }, - "arguments": { - "type": "string", - "description": "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." - } - } - } - }, - "required": [ - "index" - ] - }, - "ChatCompletionRole": { - "type": "string", - "description": "The role of the author of a message", - "enum": [ - "system", - "user", - "assistant", - "tool", - "function" - ] - }, - "ChatCompletionResponseMessage": { - "type": "object", - "description": "A chat completion message generated by the model.", - "properties": { - "content": { - "type": "string", - "description": "The contents of the message.", - "nullable": true - }, - "tool_calls": { - "$ref": "#/components/schemas/ChatCompletionMessageToolCalls" - }, - "role": { - "type": "string", - "enum": [ - "assistant" - ], - "description": "The role of the author of this message." - }, - "function_call": { - "type": "object", - "deprecated": true, - "description": "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model.", - "properties": { - "arguments": { - "type": "string", - "description": "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." - }, - "name": { - "type": "string", - "description": "The name of the function to call." - } - }, - "required": [ - "name", - "arguments" - ] - } - }, - "required": [ - "role", - "content" - ] - }, - "ChatCompletionStreamResponseDelta": { - "type": "object", - "description": "A chat completion delta generated by streamed model responses.", - "properties": { - "content": { - "type": "string", - "description": "The contents of the chunk message.", - "nullable": true - }, - "function_call": { - "deprecated": true, - "type": "object", - "description": "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model.", - "properties": { - "arguments": { - "type": "string", - "description": "The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function." - }, - "name": { - "type": "string", - "description": "The name of the function to call." - } - } - }, - "tool_calls": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChatCompletionMessageToolCallChunk" - } - }, - "role": { - "type": "string", - "enum": [ - "system", - "user", - "assistant", - "tool" - ], - "description": "The role of the author of this message." - } - } - }, - "CreateChatCompletionRequest": { - "type": "object", - "properties": { - "messages": { - "description": "A list of messages comprising the conversation so far. [Example Python code](https://cookbook.openai.com/examples/how_to_format_inputs_to_chatgpt_models).", - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/components/schemas/ChatCompletionRequestMessage" - } - }, - "model": { - "description": "ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) table for details on which models work with the Chat API.", - "example": "gpt-3.5-turbo", - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "gpt-4-1106-preview", - "gpt-4-vision-preview", - "gpt-4", - "gpt-4-0314", - "gpt-4-0613", - "gpt-4-32k", - "gpt-4-32k-0314", - "gpt-4-32k-0613", - "gpt-3.5-turbo", - "gpt-3.5-turbo-16k", - "gpt-3.5-turbo-0301", - "gpt-3.5-turbo-0613", - "gpt-3.5-turbo-1106", - "gpt-3.5-turbo-16k-0613" - ] - } - ], - "x-oaiTypeLabel": "string" - }, - "frequency_penalty": { - "type": "number", - "default": 0, - "minimum": -2, - "maximum": 2, - "nullable": true, - "description": "Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.\n\n[See more information about frequency and presence penalties.](/docs/guides/text-generation/parameter-details)\n" - }, - "logit_bias": { - "type": "object", - "x-oaiTypeLabel": "map", - "default": null, - "nullable": true, - "additionalProperties": { - "type": "integer" - }, - "description": "Modify the likelihood of specified tokens appearing in the completion.\n\nAccepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token.\n" - }, - "logprobs": { - "description": "Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the `content` of `message`. This option is currently not available on the `gpt-4-vision-preview` model.", - "type": "boolean", - "default": false, - "nullable": true - }, - "top_logprobs": { - "description": "An integer between 0 and 5 specifying the number of most likely tokens to return at each token position, each with an associated log probability. `logprobs` must be set to `true` if this parameter is used.", - "type": "integer", - "minimum": 0, - "maximum": 5, - "nullable": true - }, - "max_tokens": { - "description": "The maximum number of [tokens](/tokenizer) that can be generated in the chat completion.\n\nThe total length of input tokens and generated tokens is limited by the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens.\n", - "type": "integer", - "nullable": true - }, - "n": { - "type": "integer", - "minimum": 1, - "maximum": 128, - "default": 1, - "example": 1, - "nullable": true, - "description": "How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs." - }, - "presence_penalty": { - "type": "number", - "default": 0, - "minimum": -2, - "maximum": 2, - "nullable": true, - "description": "Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.\n\n[See more information about frequency and presence penalties.](/docs/guides/text-generation/parameter-details)\n" - }, - "response_format": { - "type": "object", - "description": "An object specifying the format that the model must output. Compatible with `gpt-4-1106-preview` and `gpt-3.5-turbo-1106`.\n\nSetting to `{ \"type\": \"json_object\" }` enables JSON mode, which guarantees the message the model generates is valid JSON.\n\n**Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly \"stuck\" request. Also note that the message content may be partially cut off if `finish_reason=\"length\"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length.\n", - "properties": { - "type": { - "type": "string", - "enum": [ - "text", - "json_object" - ], - "example": "json_object", - "default": "text", - "description": "Must be one of `text` or `json_object`." - } - } - }, - "seed": { - "type": "integer", - "minimum": -9223372036854776000, - "maximum": 9223372036854776000, - "nullable": true, - "description": "This feature is in Beta.\nIf specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result.\nDeterminism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend.\n", - "x-oaiMeta": { - "beta": true - } - }, - "stop": { - "description": "Up to 4 sequences where the API will stop generating further tokens.\n", - "default": null, - "oneOf": [ - { - "type": "string", - "nullable": true - }, - { - "type": "array", - "minItems": 1, - "maxItems": 4, - "items": { - "type": "string" - } - } - ] - }, - "stream": { - "description": "If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions).\n", - "type": "boolean", - "nullable": true, - "default": false - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2, - "default": 1, - "example": 1, - "nullable": true, - "description": "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n\nWe generally recommend altering this or `top_p` but not both.\n" - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1, - "default": 1, - "example": 1, - "nullable": true, - "description": "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - }, - "tools": { - "type": "array", - "description": "A list of tools the model may call. Currently, only functions are supported as a tool. Use this to provide a list of functions the model may generate JSON inputs for.\n", - "items": { - "$ref": "#/components/schemas/ChatCompletionTool" - } - }, - "tool_choice": { - "$ref": "#/components/schemas/ChatCompletionToolChoiceOption" - }, - "user": { - "type": "string", - "example": "user-1234", - "description": "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\n" - }, - "function_call": { - "deprecated": true, - "description": "Deprecated in favor of `tool_choice`.\n\nControls which (if any) function is called by the model.\n`none` means the model will not call a function and instead generates a message.\n`auto` means the model can pick between generating a message or calling a function.\nSpecifying a particular function via `{\"name\": \"my_function\"}` forces the model to call that function.\n\n`none` is the default when no functions are present. `auto` is the default if functions are present.\n", - "oneOf": [ - { - "type": "string", - "description": "`none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function.\n", - "enum": [ - "none", - "auto" - ] - }, - { - "$ref": "#/components/schemas/ChatCompletionFunctionCallOption" - } - ], - "x-oaiExpandable": true - }, - "functions": { - "deprecated": true, - "description": "Deprecated in favor of `tools`.\n\nA list of functions the model may generate JSON inputs for.\n", - "type": "array", - "minItems": 1, - "maxItems": 128, - "items": { - "$ref": "#/components/schemas/ChatCompletionFunctions" - } - } - }, - "required": [ - "model", - "messages" - ] - }, - "CreateChatCompletionResponse": { - "type": "object", - "description": "Represents a chat completion response returned by model, based on the provided input.", - "properties": { - "id": { - "type": "string", - "description": "A unique identifier for the chat completion." - }, - "choices": { - "type": "array", - "description": "A list of chat completion choices. Can be more than one if `n` is greater than 1.", - "items": { - "type": "object", - "required": [ - "finish_reason", - "index", - "message", - "logprobs" - ], - "properties": { - "finish_reason": { - "type": "string", - "description": "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence,\n`length` if the maximum number of tokens specified in the request was reached,\n`content_filter` if content was omitted due to a flag from our content filters,\n`tool_calls` if the model called a tool, or `function_call` (deprecated) if the model called a function.\n", - "enum": [ - "stop", - "length", - "tool_calls", - "content_filter", - "function_call" - ] - }, - "index": { - "type": "integer", - "description": "The index of the choice in the list of choices." - }, - "message": { - "$ref": "#/components/schemas/ChatCompletionResponseMessage" - }, - "logprobs": { - "description": "Log probability information for the choice.", - "type": "object", - "nullable": true, - "properties": { - "content": { - "description": "A list of message content tokens with log probability information.", - "type": "array", - "items": { - "$ref": "#/components/schemas/ChatCompletionTokenLogprob" - }, - "nullable": true - } - }, - "required": [ - "content" - ] - } - } - } - }, - "created": { - "type": "integer", - "description": "The Unix timestamp (in seconds) of when the chat completion was created." - }, - "model": { - "type": "string", - "description": "The model used for the chat completion." - }, - "system_fingerprint": { - "type": "string", - "description": "This fingerprint represents the backend configuration that the model runs with.\n\nCan be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.\n" - }, - "object": { - "type": "string", - "description": "The object type, which is always `chat.completion`.", - "enum": [ - "chat.completion" - ] - }, - "usage": { - "$ref": "#/components/schemas/CompletionUsage" - } - }, - "required": [ - "choices", - "created", - "id", - "model", - "object" - ], - "x-oaiMeta": { - "name": "The chat completion object", - "group": "chat", - "example": "{\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion\",\n \"created\": 1677652288,\n \"model\": \"gpt-3.5-turbo-0613\",\n \"system_fingerprint\": \"fp_44709d6fcb\",\n \"choices\": [{\n \"index\": 0,\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"\\n\\nHello there, how may I assist you today?\",\n },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }],\n \"usage\": {\n \"prompt_tokens\": 9,\n \"completion_tokens\": 12,\n \"total_tokens\": 21\n }\n}\n" - } - }, - "CreateChatCompletionFunctionResponse": { - "type": "object", - "description": "Represents a chat completion response returned by model, based on the provided input.", - "properties": { - "id": { - "type": "string", - "description": "A unique identifier for the chat completion." - }, - "choices": { - "type": "array", - "description": "A list of chat completion choices. Can be more than one if `n` is greater than 1.", - "items": { - "type": "object", - "required": [ - "finish_reason", - "index", - "message", - "logprobs" - ], - "properties": { - "finish_reason": { - "type": "string", - "description": "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, `length` if the maximum number of tokens specified in the request was reached, `content_filter` if content was omitted due to a flag from our content filters, or `function_call` if the model called a function.\n", - "enum": [ - "stop", - "length", - "function_call", - "content_filter" - ] - }, - "index": { - "type": "integer", - "description": "The index of the choice in the list of choices." - }, - "message": { - "$ref": "#/components/schemas/ChatCompletionResponseMessage" - } - } - } - }, - "created": { - "type": "integer", - "description": "The Unix timestamp (in seconds) of when the chat completion was created." - }, - "model": { - "type": "string", - "description": "The model used for the chat completion." - }, - "system_fingerprint": { - "type": "string", - "description": "This fingerprint represents the backend configuration that the model runs with.\n\nCan be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.\n" - }, - "object": { - "type": "string", - "description": "The object type, which is always `chat.completion`.", - "enum": [ - "chat.completion" - ] - }, - "usage": { - "$ref": "#/components/schemas/CompletionUsage" - } - }, - "required": [ - "choices", - "created", - "id", - "model", - "object" - ], - "x-oaiMeta": { - "name": "The chat completion object", - "group": "chat", - "example": "{\n \"id\": \"chatcmpl-abc123\",\n \"object\": \"chat.completion\",\n \"created\": 1699896916,\n \"model\": \"gpt-3.5-turbo-0613\",\n \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": \"assistant\",\n \"content\": null,\n \"tool_calls\": [\n {\n \"id\": \"call_abc123\",\n \"type\": \"function\",\n \"function\": {\n \"name\": \"get_current_weather\",\n \"arguments\": \"{\\n\\\"location\\\": \\\"Boston, MA\\\"\\n}\"\n }\n }\n ]\n },\n \"logprobs\": null,\n \"finish_reason\": \"tool_calls\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\": 82,\n \"completion_tokens\": 17,\n \"total_tokens\": 99\n }\n}\n" - } - }, - "ChatCompletionTokenLogprob": { - "type": "object", - "properties": { - "token": { - "description": "The token.", - "type": "string" - }, - "logprob": { - "description": "The log probability of this token.", - "type": "number" - }, - "bytes": { - "description": "A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be `null` if there is no bytes representation for the token.", - "type": "array", - "items": { - "type": "integer" - }, - "nullable": true - }, - "top_logprobs": { - "description": "List of the most likely tokens and their log probability, at this token position. In rare cases, there may be fewer than the number of requested `top_logprobs` returned.", - "type": "array", - "items": { - "type": "object", - "properties": { - "token": { - "description": "The token.", - "type": "string" - }, - "logprob": { - "description": "The log probability of this token.", - "type": "number" - }, - "bytes": { - "description": "A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be `null` if there is no bytes representation for the token.", - "type": "array", - "items": { - "type": "integer" - }, - "nullable": true - } - }, - "required": [ - "token", - "logprob", - "bytes" - ] - } - } - }, - "required": [ - "token", - "logprob", - "bytes", - "top_logprobs" - ] - }, - "ListPaginatedFineTuningJobsResponse": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FineTuningJob" - } - }, - "has_more": { - "type": "boolean" - }, - "object": { - "type": "string", - "enum": [ - "list" - ] - } - }, - "required": [ - "object", - "data", - "has_more" - ] - }, - "CreateChatCompletionStreamResponse": { - "type": "object", - "description": "Represents a streamed chunk of a chat completion response returned by model, based on the provided input.", - "properties": { - "id": { - "type": "string", - "description": "A unique identifier for the chat completion. Each chunk has the same ID." - }, - "choices": { - "type": "array", - "description": "A list of chat completion choices. Can be more than one if `n` is greater than 1.", - "items": { - "type": "object", - "required": [ - "delta", - "finish_reason", - "index" - ], - "properties": { - "delta": { - "$ref": "#/components/schemas/ChatCompletionStreamResponseDelta" - }, - "logprobs": { - "description": "Log probability information for the choice.", - "type": "object", - "nullable": true, - "properties": { - "content": { - "description": "A list of message content tokens with log probability information.", - "type": "array", - "items": { - "$ref": "#/components/schemas/ChatCompletionTokenLogprob" - }, - "nullable": true - } - }, - "required": [ - "content" - ] - }, - "finish_reason": { - "type": "string", - "description": "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence,\n`length` if the maximum number of tokens specified in the request was reached,\n`content_filter` if content was omitted due to a flag from our content filters,\n`tool_calls` if the model called a tool, or `function_call` (deprecated) if the model called a function.\n", - "enum": [ - "stop", - "length", - "tool_calls", - "content_filter", - "function_call" - ], - "nullable": true - }, - "index": { - "type": "integer", - "description": "The index of the choice in the list of choices." - } - } - } - }, - "created": { - "type": "integer", - "description": "The Unix timestamp (in seconds) of when the chat completion was created. Each chunk has the same timestamp." - }, - "model": { - "type": "string", - "description": "The model to generate the completion." - }, - "system_fingerprint": { - "type": "string", - "description": "This fingerprint represents the backend configuration that the model runs with.\nCan be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism.\n" - }, - "object": { - "type": "string", - "description": "The object type, which is always `chat.completion.chunk`.", - "enum": [ - "chat.completion.chunk" - ] - } - }, - "required": [ - "choices", - "created", - "id", - "model", - "object" - ], - "x-oaiMeta": { - "name": "The chat completion chunk object", - "group": "chat", - "example": "{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"logprobs\":null,\"finish_reason\":null}]}\n\n{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{\"content\":\"Hello\"},\"logprobs\":null,\"finish_reason\":null}]}\n\n{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{\"content\":\"!\"},\"logprobs\":null,\"finish_reason\":null}]}\n\n....\n\n{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{\"content\":\" today\"},\"logprobs\":null,\"finish_reason\":null}]}\n\n{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{\"content\":\"?\"},\"logprobs\":null,\"finish_reason\":null}]}\n\n{\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1694268190,\"model\":\"gpt-3.5-turbo-0613\", \"system_fingerprint\": \"fp_44709d6fcb\", \"choices\":[{\"index\":0,\"delta\":{},\"logprobs\":null,\"finish_reason\":\"stop\"}]}\n" - } - }, - "CreateChatCompletionImageResponse": { - "type": "object", - "description": "Represents a streamed chunk of a chat completion response returned by model, based on the provided input.", - "x-oaiMeta": { - "name": "The chat completion chunk object", - "group": "chat", - "example": "{\n \"id\": \"chatcmpl-123\",\n \"object\": \"chat.completion\",\n \"created\": 1677652288,\n \"model\": \"gpt-3.5-turbo-0613\",\n \"system_fingerprint\": \"fp_44709d6fcb\",\n \"choices\": [{\n \"index\": 0,\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"\\n\\nHello there, how may I assist you today?\",\n },\n \"logprobs\": null,\n \"finish_reason\": \"stop\"\n }],\n \"usage\": {\n \"prompt_tokens\": 9,\n \"completion_tokens\": 12,\n \"total_tokens\": 21\n }\n}\n" - } - }, - "CreateEditRequest": { - "type": "object", - "properties": { - "instruction": { - "description": "The instruction that tells the model how to edit the prompt.", - "type": "string", - "example": "Fix the spelling mistakes." - }, - "model": { - "description": "ID of the model to use. You can use the `text-davinci-edit-001` or `code-davinci-edit-001` model with this endpoint.", - "example": "text-davinci-edit-001", - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "text-davinci-edit-001", - "code-davinci-edit-001" - ] - } - ], - "x-oaiTypeLabel": "string" - }, - "input": { - "description": "The input text to use as a starting point for the edit.", - "type": "string", - "default": "", - "nullable": true, - "example": "What day of the wek is it?" - }, - "n": { - "type": "integer", - "minimum": 1, - "maximum": 20, - "default": 1, - "example": 1, - "nullable": true, - "description": "How many edits to generate for the input and instruction." - }, - "temperature": { - "type": "number", - "minimum": 0, - "maximum": 2, - "default": 1, - "example": 1, - "nullable": true, - "description": "What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic.\n\nWe generally recommend altering this or `top_p` but not both.\n" - }, - "top_p": { - "type": "number", - "minimum": 0, - "maximum": 1, - "default": 1, - "example": 1, - "nullable": true, - "description": "An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.\n\nWe generally recommend altering this or `temperature` but not both.\n" - } - }, - "required": [ - "model", - "instruction" - ] - }, - "CreateEditResponse": { - "type": "object", - "deprecated": true, - "title": "Edit", - "properties": { - "choices": { - "type": "array", - "description": "A list of edit choices. Can be more than one if `n` is greater than 1.", - "items": { - "type": "object", - "required": [ - "text", - "index", - "finish_reason" - ], - "properties": { - "finish_reason": { - "type": "string", - "description": "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence,\n`length` if the maximum number of tokens specified in the request was reached,\nor `content_filter` if content was omitted due to a flag from our content filters.\n", - "enum": [ - "stop", - "length" - ] - }, - "index": { - "type": "integer", - "description": "The index of the choice in the list of choices." - }, - "text": { - "type": "string", - "description": "The edited result." - } - } - } - }, - "object": { - "type": "string", - "description": "The object type, which is always `edit`.", - "enum": [ - "edit" - ] - }, - "created": { - "type": "integer", - "description": "The Unix timestamp (in seconds) of when the edit was created." - }, - "usage": { - "$ref": "#/components/schemas/CompletionUsage" - } - }, - "required": [ - "object", - "created", - "choices", - "usage" - ], - "x-oaiMeta": { - "name": "The edit object", - "example": "{\n \"object\": \"edit\",\n \"created\": 1589478378,\n \"choices\": [\n {\n \"text\": \"What day of the week is it?\",\n \"index\": 0,\n }\n ],\n \"usage\": {\n \"prompt_tokens\": 25,\n \"completion_tokens\": 32,\n \"total_tokens\": 57\n }\n}\n" - } - }, - "CreateImageRequest": { - "type": "object", - "properties": { - "prompt": { - "description": "A text description of the desired image(s). The maximum length is 1000 characters for `dall-e-2` and 4000 characters for `dall-e-3`.", - "type": "string", - "example": "A cute baby sea otter" - }, - "model": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "dall-e-2", - "dall-e-3" - ] - } - ], - "x-oaiTypeLabel": "string", - "default": "dall-e-2", - "example": "dall-e-3", - "nullable": true, - "description": "The model to use for image generation." - }, - "n": { - "type": "integer", - "minimum": 1, - "maximum": 10, - "default": 1, - "example": 1, - "nullable": true, - "description": "The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported." - }, - "quality": { - "type": "string", - "enum": [ - "standard", - "hd" - ], - "default": "standard", - "example": "standard", - "description": "The quality of the image that will be generated. `hd` creates images with finer details and greater consistency across the image. This param is only supported for `dall-e-3`." - }, - "response_format": { - "type": "string", - "enum": [ - "url", - "b64_json" - ], - "default": "url", - "example": "url", - "nullable": true, - "description": "The format in which the generated images are returned. Must be one of `url` or `b64_json`." - }, - "size": { - "type": "string", - "enum": [ - "256x256", - "512x512", - "1024x1024", - "1792x1024", - "1024x1792" - ], - "default": "1024x1024", - "example": "1024x1024", - "nullable": true, - "description": "The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`. Must be one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3` models." - }, - "style": { - "type": "string", - "enum": [ - "vivid", - "natural" - ], - "default": "vivid", - "example": "vivid", - "nullable": true, - "description": "The style of the generated images. Must be one of `vivid` or `natural`. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. This param is only supported for `dall-e-3`." - }, - "user": { - "type": "string", - "example": "user-1234", - "description": "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\n" - } - }, - "required": [ - "prompt" - ] - }, - "ImagesResponse": { - "properties": { - "created": { - "type": "integer" - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Image" - } - } - }, - "required": [ - "created", - "data" - ] - }, - "Image": { - "type": "object", - "description": "Represents the url or the content of an image generated by the OpenAI API.", - "properties": { - "b64_json": { - "type": "string", - "description": "The base64-encoded JSON of the generated image, if `response_format` is `b64_json`." - }, - "url": { - "type": "string", - "description": "The URL of the generated image, if `response_format` is `url` (default)." - }, - "revised_prompt": { - "type": "string", - "description": "The prompt that was used to generate the image, if there was any revision to the prompt." - } - }, - "x-oaiMeta": { - "name": "The image object", - "example": "{\n \"url\": \"...\",\n \"revised_prompt\": \"...\"\n}\n" - } - }, - "CreateImageEditRequest": { - "type": "object", - "properties": { - "image": { - "description": "The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not provided, image must have transparency, which will be used as the mask.", - "type": "string", - "format": "binary" - }, - "prompt": { - "description": "A text description of the desired image(s). The maximum length is 1000 characters.", - "type": "string", - "example": "A cute baby sea otter wearing a beret" - }, - "mask": { - "description": "An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`.", - "type": "string", - "format": "binary" - }, - "model": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "dall-e-2" - ] - } - ], - "x-oaiTypeLabel": "string", - "default": "dall-e-2", - "example": "dall-e-2", - "nullable": true, - "description": "The model to use for image generation. Only `dall-e-2` is supported at this time." - }, - "n": { - "type": "integer", - "minimum": 1, - "maximum": 10, - "default": 1, - "example": 1, - "nullable": true, - "description": "The number of images to generate. Must be between 1 and 10." - }, - "size": { - "type": "string", - "enum": [ - "256x256", - "512x512", - "1024x1024" - ], - "default": "1024x1024", - "example": "1024x1024", - "nullable": true, - "description": "The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`." - }, - "response_format": { - "type": "string", - "enum": [ - "url", - "b64_json" - ], - "default": "url", - "example": "url", - "nullable": true, - "description": "The format in which the generated images are returned. Must be one of `url` or `b64_json`." - }, - "user": { - "type": "string", - "example": "user-1234", - "description": "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\n" - } - }, - "required": [ - "prompt", - "image" - ] - }, - "CreateImageVariationRequest": { - "type": "object", - "properties": { - "image": { - "description": "The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, and square.", - "type": "string", - "format": "binary" - }, - "model": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "dall-e-2" - ] - } - ], - "x-oaiTypeLabel": "string", - "default": "dall-e-2", - "example": "dall-e-2", - "nullable": true, - "description": "The model to use for image generation. Only `dall-e-2` is supported at this time." - }, - "n": { - "type": "integer", - "minimum": 1, - "maximum": 10, - "default": 1, - "example": 1, - "nullable": true, - "description": "The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported." - }, - "response_format": { - "type": "string", - "enum": [ - "url", - "b64_json" - ], - "default": "url", - "example": "url", - "nullable": true, - "description": "The format in which the generated images are returned. Must be one of `url` or `b64_json`." - }, - "size": { - "type": "string", - "enum": [ - "256x256", - "512x512", - "1024x1024" - ], - "default": "1024x1024", - "example": "1024x1024", - "nullable": true, - "description": "The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`." - }, - "user": { - "type": "string", - "example": "user-1234", - "description": "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\n" - } - }, - "required": [ - "image" - ] - }, - "CreateModerationRequest": { - "type": "object", - "properties": { - "input": { - "description": "The input text to classify", - "oneOf": [ - { - "type": "string", - "default": "", - "example": "I want to kill them." - }, - { - "type": "array", - "items": { - "type": "string", - "default": "", - "example": "I want to kill them." - } - } - ] - }, - "model": { - "description": "Two content moderations models are available: `text-moderation-stable` and `text-moderation-latest`.\n\nThe default is `text-moderation-latest` which will be automatically upgraded over time. This ensures you are always using our most accurate model. If you use `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`.\n", - "nullable": false, - "default": "text-moderation-latest", - "example": "text-moderation-stable", - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "text-moderation-latest", - "text-moderation-stable" - ] - } - ], - "x-oaiTypeLabel": "string" - } - }, - "required": [ - "input" - ] - }, - "CreateModerationResponse": { - "type": "object", - "description": "Represents policy compliance report by OpenAI's content moderation model against a given input.", - "properties": { - "id": { - "type": "string", - "description": "The unique identifier for the moderation request." - }, - "model": { - "type": "string", - "description": "The model used to generate the moderation results." - }, - "results": { - "type": "array", - "description": "A list of moderation objects.", - "items": { - "type": "object", - "properties": { - "flagged": { - "type": "boolean", - "description": "Whether the content violates [OpenAI's usage policies](/policies/usage-policies)." - }, - "categories": { - "type": "object", - "description": "A list of the categories, and whether they are flagged or not.", - "properties": { - "hate": { - "type": "boolean", - "description": "Content that expresses, incites, or promotes hate based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. Hateful content aimed at non-protected groups (e.g., chess players) is harassment." - }, - "hate/threatening": { - "type": "boolean", - "description": "Hateful content that also includes violence or serious harm towards the targeted group based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste." - }, - "harassment": { - "type": "boolean", - "description": "Content that expresses, incites, or promotes harassing language towards any target." - }, - "harassment/threatening": { - "type": "boolean", - "description": "Harassment content that also includes violence or serious harm towards any target." - }, - "self-harm": { - "type": "boolean", - "description": "Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, and eating disorders." - }, - "self-harm/intent": { - "type": "boolean", - "description": "Content where the speaker expresses that they are engaging or intend to engage in acts of self-harm, such as suicide, cutting, and eating disorders." - }, - "self-harm/instructions": { - "type": "boolean", - "description": "Content that encourages performing acts of self-harm, such as suicide, cutting, and eating disorders, or that gives instructions or advice on how to commit such acts." - }, - "sexual": { - "type": "boolean", - "description": "Content meant to arouse sexual excitement, such as the description of sexual activity, or that promotes sexual services (excluding sex education and wellness)." - }, - "sexual/minors": { - "type": "boolean", - "description": "Sexual content that includes an individual who is under 18 years old." - }, - "violence": { - "type": "boolean", - "description": "Content that depicts death, violence, or physical injury." - }, - "violence/graphic": { - "type": "boolean", - "description": "Content that depicts death, violence, or physical injury in graphic detail." - } - }, - "required": [ - "hate", - "hate/threatening", - "harassment", - "harassment/threatening", - "self-harm", - "self-harm/intent", - "self-harm/instructions", - "sexual", - "sexual/minors", - "violence", - "violence/graphic" - ] - }, - "category_scores": { - "type": "object", - "description": "A list of the categories along with their scores as predicted by model.", - "properties": { - "hate": { - "type": "number", - "description": "The score for the category 'hate'." - }, - "hate/threatening": { - "type": "number", - "description": "The score for the category 'hate/threatening'." - }, - "harassment": { - "type": "number", - "description": "The score for the category 'harassment'." - }, - "harassment/threatening": { - "type": "number", - "description": "The score for the category 'harassment/threatening'." - }, - "self-harm": { - "type": "number", - "description": "The score for the category 'self-harm'." - }, - "self-harm/intent": { - "type": "number", - "description": "The score for the category 'self-harm/intent'." - }, - "self-harm/instructions": { - "type": "number", - "description": "The score for the category 'self-harm/instructions'." - }, - "sexual": { - "type": "number", - "description": "The score for the category 'sexual'." - }, - "sexual/minors": { - "type": "number", - "description": "The score for the category 'sexual/minors'." - }, - "violence": { - "type": "number", - "description": "The score for the category 'violence'." - }, - "violence/graphic": { - "type": "number", - "description": "The score for the category 'violence/graphic'." - } - }, - "required": [ - "hate", - "hate/threatening", - "harassment", - "harassment/threatening", - "self-harm", - "self-harm/intent", - "self-harm/instructions", - "sexual", - "sexual/minors", - "violence", - "violence/graphic" - ] - } - }, - "required": [ - "flagged", - "categories", - "category_scores" - ] - } - } - }, - "required": [ - "id", - "model", - "results" - ], - "x-oaiMeta": { - "name": "The moderation object", - "example": "{\n \"id\": \"modr-XXXXX\",\n \"model\": \"text-moderation-005\",\n \"results\": [\n {\n \"flagged\": true,\n \"categories\": {\n \"sexual\": false,\n \"hate\": false,\n \"harassment\": false,\n \"self-harm\": false,\n \"sexual/minors\": false,\n \"hate/threatening\": false,\n \"violence/graphic\": false,\n \"self-harm/intent\": false,\n \"self-harm/instructions\": false,\n \"harassment/threatening\": true,\n \"violence\": true,\n },\n \"category_scores\": {\n \"sexual\": 1.2282071e-06,\n \"hate\": 0.010696256,\n \"harassment\": 0.29842457,\n \"self-harm\": 1.5236925e-08,\n \"sexual/minors\": 5.7246268e-08,\n \"hate/threatening\": 0.0060676364,\n \"violence/graphic\": 4.435014e-06,\n \"self-harm/intent\": 8.098441e-10,\n \"self-harm/instructions\": 2.8498655e-11,\n \"harassment/threatening\": 0.63055265,\n \"violence\": 0.99011886,\n }\n }\n ]\n}\n" - } - }, - "ListFilesResponse": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIFile" - } - }, - "object": { - "type": "string", - "enum": [ - "list" - ] - } - }, - "required": [ - "object", - "data" - ] - }, - "CreateFileRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "file": { - "description": "The File object (not file name) to be uploaded.\n", - "type": "string", - "format": "binary" - }, - "purpose": { - "description": "The intended purpose of the uploaded file.\n\nUse \"fine-tune\" for [Fine-tuning](/docs/api-reference/fine-tuning) and \"assistants\" for [Assistants](/docs/api-reference/assistants) and [Messages](/docs/api-reference/messages). This allows us to validate the format of the uploaded file is correct for fine-tuning.\n", - "type": "string", - "enum": [ - "fine-tune", - "assistants" - ] - } - }, - "required": [ - "file", - "purpose" - ] - }, - "DeleteFileResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "object": { - "type": "string", - "enum": [ - "file" - ] - }, - "deleted": { - "type": "boolean" - } - }, - "required": [ - "id", - "object", - "deleted" - ] - }, - "CreateFineTuningJobRequest": { - "type": "object", - "properties": { - "model": { - "description": "The name of the model to fine-tune. You can select one of the\n[supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned).\n", - "example": "gpt-3.5-turbo", - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "babbage-002", - "davinci-002", - "gpt-3.5-turbo" - ] - } - ], - "x-oaiTypeLabel": "string" - }, - "training_file": { - "description": "The ID of an uploaded file that contains training data.\n\nSee [upload file](/docs/api-reference/files/upload) for how to upload a file.\n\nYour dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose `fine-tune`.\n\nSee the [fine-tuning guide](/docs/guides/fine-tuning) for more details.\n", - "type": "string", - "example": "file-abc123" - }, - "hyperparameters": { - "type": "object", - "description": "The hyperparameters used for the fine-tuning job.", - "properties": { - "batch_size": { - "description": "Number of examples in each batch. A larger batch size means that model parameters\nare updated less frequently, but with lower variance.\n", - "oneOf": [ - { - "type": "string", - "enum": [ - "auto" - ] - }, - { - "type": "integer", - "minimum": 1, - "maximum": 256 - } - ], - "default": "auto" - }, - "learning_rate_multiplier": { - "description": "Scaling factor for the learning rate. A smaller learning rate may be useful to avoid\noverfitting.\n", - "oneOf": [ - { - "type": "string", - "enum": [ - "auto" - ] - }, - { - "type": "number", - "minimum": 0, - "exclusiveMinimum": true - } - ], - "default": "auto" - }, - "n_epochs": { - "description": "The number of epochs to train the model for. An epoch refers to one full cycle\nthrough the training dataset.\n", - "oneOf": [ - { - "type": "string", - "enum": [ - "auto" - ] - }, - { - "type": "integer", - "minimum": 1, - "maximum": 50 - } - ], - "default": "auto" - } - } - }, - "suffix": { - "description": "A string of up to 18 characters that will be added to your fine-tuned model name.\n\nFor example, a `suffix` of \"custom-model-name\" would produce a model name like `ft:gpt-3.5-turbo:openai:custom-model-name:7p4lURel`.\n", - "type": "string", - "minLength": 1, - "maxLength": 40, - "default": null, - "nullable": true - }, - "validation_file": { - "description": "The ID of an uploaded file that contains validation data.\n\nIf you provide this file, the data is used to generate validation\nmetrics periodically during fine-tuning. These metrics can be viewed in\nthe fine-tuning results file.\nThe same data should not be present in both train and validation files.\n\nYour dataset must be formatted as a JSONL file. You must upload your file with the purpose `fine-tune`.\n\nSee the [fine-tuning guide](/docs/guides/fine-tuning) for more details.\n", - "type": "string", - "nullable": true, - "example": "file-abc123" - } - }, - "required": [ - "model", - "training_file" - ] - }, - "ListFineTuningJobEventsResponse": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FineTuningJobEvent" - } - }, - "object": { - "type": "string", - "enum": [ - "list" - ] - } - }, - "required": [ - "object", - "data" - ] - }, - "CreateFineTuneRequest": { - "type": "object", - "properties": { - "training_file": { - "description": "The ID of an uploaded file that contains training data.\n\nSee [upload file](/docs/api-reference/files/upload) for how to upload a file.\n\nYour dataset must be formatted as a JSONL file, where each training\nexample is a JSON object with the keys \"prompt\" and \"completion\".\nAdditionally, you must upload your file with the purpose `fine-tune`.\n\nSee the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more details.\n", - "type": "string", - "example": "file-abc123" - }, - "batch_size": { - "description": "The batch size to use for training. The batch size is the number of\ntraining examples used to train a single forward and backward pass.\n\nBy default, the batch size will be dynamically configured to be\n~0.2% of the number of examples in the training set, capped at 256 -\nin general, we've found that larger batch sizes tend to work better\nfor larger datasets.\n", - "default": null, - "type": "integer", - "nullable": true - }, - "classification_betas": { - "description": "If this is provided, we calculate F-beta scores at the specified\nbeta values. The F-beta score is a generalization of F-1 score.\nThis is only used for binary classification.\n\nWith a beta of 1 (i.e. the F-1 score), precision and recall are\ngiven the same weight. A larger beta score puts more weight on\nrecall and less on precision. A smaller beta score puts more weight\non precision and less on recall.\n", - "type": "array", - "items": { - "type": "number" - }, - "example": [ - 0.6, - 1, - 1.5, - 2 - ], - "default": null, - "nullable": true - }, - "classification_n_classes": { - "description": "The number of classes in a classification task.\n\nThis parameter is required for multiclass classification.\n", - "type": "integer", - "default": null, - "nullable": true - }, - "classification_positive_class": { - "description": "The positive class in binary classification.\n\nThis parameter is needed to generate precision, recall, and F1\nmetrics when doing binary classification.\n", - "type": "string", - "default": null, - "nullable": true - }, - "compute_classification_metrics": { - "description": "If set, we calculate classification-specific metrics such as accuracy\nand F-1 score using the validation set at the end of every epoch.\nThese metrics can be viewed in the [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model).\n\nIn order to compute classification metrics, you must provide a\n`validation_file`. Additionally, you must\nspecify `classification_n_classes` for multiclass classification or\n`classification_positive_class` for binary classification.\n", - "type": "boolean", - "default": false, - "nullable": true - }, - "hyperparameters": { - "type": "object", - "description": "The hyperparameters used for the fine-tuning job.", - "properties": { - "n_epochs": { - "description": "The number of epochs to train the model for. An epoch refers to one\nfull cycle through the training dataset.\n", - "oneOf": [ - { - "type": "string", - "enum": [ - "auto" - ] - }, - { - "type": "integer", - "minimum": 1, - "maximum": 50 - } - ], - "default": "auto" - } - } - }, - "learning_rate_multiplier": { - "description": "The learning rate multiplier to use for training.\nThe fine-tuning learning rate is the original learning rate used for\npretraining multiplied by this value.\n\nBy default, the learning rate multiplier is the 0.05, 0.1, or 0.2\ndepending on final `batch_size` (larger learning rates tend to\nperform better with larger batch sizes). We recommend experimenting\nwith values in the range 0.02 to 0.2 to see what produces the best\nresults.\n", - "default": null, - "type": "number", - "nullable": true - }, - "model": { - "description": "The name of the base model to fine-tune. You can select one of \"ada\",\n\"babbage\", \"curie\", \"davinci\", or a fine-tuned model created after 2022-04-21 and before 2023-08-22.\nTo learn more about these models, see the\n[Models](/docs/models) documentation.\n", - "default": "curie", - "example": "curie", - "nullable": true, - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "ada", - "babbage", - "curie", - "davinci" - ] - } - ], - "x-oaiTypeLabel": "string" - }, - "prompt_loss_weight": { - "description": "The weight to use for loss on the prompt tokens. This controls how\nmuch the model tries to learn to generate the prompt (as compared\nto the completion which always has a weight of 1.0), and can add\na stabilizing effect to training when completions are short.\n\nIf prompts are extremely long (relative to completions), it may make\nsense to reduce this weight so as to avoid over-prioritizing\nlearning the prompt.\n", - "default": 0.01, - "type": "number", - "nullable": true - }, - "suffix": { - "description": "A string of up to 40 characters that will be added to your fine-tuned model name.\n\nFor example, a `suffix` of \"custom-model-name\" would produce a model name like `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`.\n", - "type": "string", - "minLength": 1, - "maxLength": 40, - "default": null, - "nullable": true - }, - "validation_file": { - "description": "The ID of an uploaded file that contains validation data.\n\nIf you provide this file, the data is used to generate validation\nmetrics periodically during fine-tuning. These metrics can be viewed in\nthe [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model).\nYour train and validation data should be mutually exclusive.\n\nYour dataset must be formatted as a JSONL file, where each validation\nexample is a JSON object with the keys \"prompt\" and \"completion\".\nAdditionally, you must upload your file with the purpose `fine-tune`.\n\nSee the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more details.\n", - "type": "string", - "nullable": true, - "example": "file-abc123" - } - }, - "required": [ - "training_file" - ] - }, - "ListFineTunesResponse": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FineTune" - } - }, - "object": { - "type": "string", - "enum": [ - "list" - ] - } - }, - "required": [ - "object", - "data" - ] - }, - "ListFineTuneEventsResponse": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FineTuneEvent" - } - }, - "object": { - "type": "string", - "enum": [ - "list" - ] - } - }, - "required": [ - "object", - "data" - ] - }, - "CreateEmbeddingRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "input": { - "description": "Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or array of token arrays. The input must not exceed the max input tokens for the model (8192 tokens for `text-embedding-ada-002`), cannot be an empty string, and any array must be 2048 dimensions or less. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens.\n", - "example": "The quick brown fox jumped over the lazy dog", - "oneOf": [ - { - "type": "string", - "title": "string", - "description": "The string that will be turned into an embedding.", - "default": "", - "example": "This is a test." - }, - { - "type": "array", - "title": "array", - "description": "The array of strings that will be turned into an embedding.", - "minItems": 1, - "maxItems": 2048, - "items": { - "type": "string", - "default": "", - "example": "['This is a test.']" - } - }, - { - "type": "array", - "title": "array", - "description": "The array of integers that will be turned into an embedding.", - "minItems": 1, - "maxItems": 2048, - "items": { - "type": "integer" - }, - "example": "[1212, 318, 257, 1332, 13]" - }, - { - "type": "array", - "title": "array", - "description": "The array of arrays containing integers that will be turned into an embedding.", - "minItems": 1, - "maxItems": 2048, - "items": { - "type": "array", - "minItems": 1, - "items": { - "type": "integer" - } - }, - "example": "[[1212, 318, 257, 1332, 13]]" - } - ], - "x-oaiExpandable": true - }, - "model": { - "description": "ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them.\n", - "example": "text-embedding-ada-002", - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "text-embedding-ada-002" - ] - } - ], - "x-oaiTypeLabel": "string" - }, - "encoding_format": { - "description": "The format to return the embeddings in. Can be either `float` or [`base64`](https://pypi.org/project/pybase64/).", - "example": "float", - "default": "float", - "type": "string", - "enum": [ - "float", - "base64" - ] - }, - "user": { - "type": "string", - "example": "user-1234", - "description": "A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids).\n" - } - }, - "required": [ - "model", - "input" - ] - }, - "CreateEmbeddingResponse": { - "type": "object", - "properties": { - "data": { - "type": "array", - "description": "The list of embeddings generated by the model.", - "items": { - "$ref": "#/components/schemas/Embedding" - } - }, - "model": { - "type": "string", - "description": "The name of the model used to generate the embedding." - }, - "object": { - "type": "string", - "description": "The object type, which is always \"list\".", - "enum": [ - "list" - ] - }, - "usage": { - "type": "object", - "description": "The usage information for the request.", - "properties": { - "prompt_tokens": { - "type": "integer", - "description": "The number of tokens used by the prompt." - }, - "total_tokens": { - "type": "integer", - "description": "The total number of tokens used by the request." - } - }, - "required": [ - "prompt_tokens", - "total_tokens" - ] - } - }, - "required": [ - "object", - "model", - "data", - "usage" - ] - }, - "CreateTranscriptionRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "file": { - "description": "The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm.\n", - "type": "string", - "x-oaiTypeLabel": "file", - "format": "binary" - }, - "model": { - "description": "ID of the model to use. Only `whisper-1` is currently available.\n", - "example": "whisper-1", - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "whisper-1" - ] - } - ], - "x-oaiTypeLabel": "string" - }, - "language": { - "description": "The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy and latency.\n", - "type": "string" - }, - "prompt": { - "description": "An optional text to guide the model's style or continue a previous audio segment. The [prompt](/docs/guides/speech-to-text/prompting) should match the audio language.\n", - "type": "string" - }, - "response_format": { - "description": "The format of the transcript output, in one of these options: `json`, `text`, `srt`, `verbose_json`, or `vtt`.\n", - "type": "string", - "enum": [ - "json", - "text", - "srt", - "verbose_json", - "vtt" - ], - "default": "json" - }, - "temperature": { - "description": "The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit.\n", - "type": "number", - "default": 0 - } - }, - "required": [ - "file", - "model" - ] - }, - "CreateTranscriptionResponse": { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - "CreateTranslationRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "file": { - "description": "The audio file object (not file name) translate, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm.\n", - "type": "string", - "x-oaiTypeLabel": "file", - "format": "binary" - }, - "model": { - "description": "ID of the model to use. Only `whisper-1` is currently available.\n", - "example": "whisper-1", - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "whisper-1" - ] - } - ], - "x-oaiTypeLabel": "string" - }, - "prompt": { - "description": "An optional text to guide the model's style or continue a previous audio segment. The [prompt](/docs/guides/speech-to-text/prompting) should be in English.\n", - "type": "string" - }, - "response_format": { - "description": "The format of the transcript output, in one of these options: `json`, `text`, `srt`, `verbose_json`, or `vtt`.\n", - "type": "string", - "default": "json" - }, - "temperature": { - "description": "The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit.\n", - "type": "number", - "default": 0 - } - }, - "required": [ - "file", - "model" - ] - }, - "CreateTranslationResponse": { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - "CreateSpeechRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "model": { - "description": "One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`\n", - "anyOf": [ - { - "type": "string" - }, - { - "type": "string", - "enum": [ - "tts-1", - "tts-1-hd" - ] - } - ], - "x-oaiTypeLabel": "string" - }, - "input": { - "type": "string", - "description": "The text to generate audio for. The maximum length is 4096 characters.", - "maxLength": 4096 - }, - "voice": { - "description": "The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the [Text to speech guide](/docs/guides/text-to-speech/voice-options).", - "type": "string", - "enum": [ - "alloy", - "echo", - "fable", - "onyx", - "nova", - "shimmer" - ] - }, - "response_format": { - "description": "The format to audio in. Supported formats are `mp3`, `opus`, `aac`, and `flac`.", - "default": "mp3", - "type": "string", - "enum": [ - "mp3", - "opus", - "aac", - "flac" - ] - }, - "speed": { - "description": "The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default.", - "type": "number", - "default": 1, - "minimum": 0.25, - "maximum": 4 - } - }, - "required": [ - "model", - "input", - "voice" - ] - }, - "Model": { - "title": "Model", - "description": "Describes an OpenAI model offering that can be used with the API.", - "properties": { - "id": { - "type": "string", - "description": "The model identifier, which can be referenced in the API endpoints." - }, - "created": { - "type": "integer", - "description": "The Unix timestamp (in seconds) when the model was created." - }, - "object": { - "type": "string", - "description": "The object type, which is always \"model\".", - "enum": [ - "model" - ] - }, - "owned_by": { - "type": "string", - "description": "The organization that owns the model." - } - }, - "required": [ - "id", - "object", - "created", - "owned_by" - ], - "x-oaiMeta": { - "name": "The model object", - "example": "{\n \"id\": \"VAR_model_id\",\n \"object\": \"model\",\n \"created\": 1686935002,\n \"owned_by\": \"openai\"\n}\n" - } - }, - "OpenAIFile": { - "title": "OpenAIFile", - "description": "The `File` object represents a document that has been uploaded to OpenAI.", - "properties": { - "id": { - "type": "string", - "description": "The file identifier, which can be referenced in the API endpoints." - }, - "bytes": { - "type": "integer", - "description": "The size of the file, in bytes." - }, - "created_at": { - "type": "integer", - "description": "The Unix timestamp (in seconds) for when the file was created." - }, - "filename": { - "type": "string", - "description": "The name of the file." - }, - "object": { - "type": "string", - "description": "The object type, which is always `file`.", - "enum": [ - "file" - ] - }, - "purpose": { - "type": "string", - "description": "The intended purpose of the file. Supported values are `fine-tune`, `fine-tune-results`, `assistants`, and `assistants_output`.", - "enum": [ - "fine-tune", - "fine-tune-results", - "assistants", - "assistants_output" - ] - }, - "status": { - "type": "string", - "deprecated": true, - "description": "Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or `error`.", - "enum": [ - "uploaded", - "processed", - "error" - ] - }, - "status_details": { - "type": "string", - "deprecated": true, - "description": "Deprecated. For details on why a fine-tuning training file failed validation, see the `error` field on `fine_tuning.job`." - } - }, - "required": [ - "id", - "object", - "bytes", - "created_at", - "filename", - "purpose", - "status" - ], - "x-oaiMeta": { - "name": "The File object", - "example": "{\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"bytes\": 120000,\n \"created_at\": 1677610602,\n \"filename\": \"salesOverview.pdf\",\n \"purpose\": \"assistants\",\n}\n" - } - }, - "Embedding": { - "type": "object", - "description": "Represents an embedding vector returned by embedding endpoint.\n", - "properties": { - "index": { - "type": "integer", - "description": "The index of the embedding in the list of embeddings." - }, - "embedding": { - "type": "array", - "description": "The embedding vector, which is a list of floats. The length of vector depends on the model as listed in the [embedding guide](/docs/guides/embeddings).\n", - "items": { - "type": "number" - } - }, - "object": { - "type": "string", - "description": "The object type, which is always \"embedding\".", - "enum": [ - "embedding" - ] - } - }, - "required": [ - "index", - "object", - "embedding" - ], - "x-oaiMeta": { - "name": "The embedding object", - "example": "{\n \"object\": \"embedding\",\n \"embedding\": [\n 0.0023064255,\n -0.009327292,\n .... (1536 floats total for ada-002)\n -0.0028842222,\n ],\n \"index\": 0\n}\n" - } - }, - "FineTuningJob": { - "type": "object", - "title": "FineTuningJob", - "description": "The `fine_tuning.job` object represents a fine-tuning job that has been created through the API.\n", - "properties": { - "id": { - "type": "string", - "description": "The object identifier, which can be referenced in the API endpoints." - }, - "created_at": { - "type": "integer", - "description": "The Unix timestamp (in seconds) for when the fine-tuning job was created." - }, - "error": { - "type": "object", - "nullable": true, - "description": "For fine-tuning jobs that have `failed`, this will contain more information on the cause of the failure.", - "properties": { - "code": { - "type": "string", - "description": "A machine-readable error code." - }, - "message": { - "type": "string", - "description": "A human-readable error message." - }, - "param": { - "type": "string", - "description": "The parameter that was invalid, usually `training_file` or `validation_file`. This field will be null if the failure was not parameter-specific.", - "nullable": true - } - }, - "required": [ - "code", - "message", - "param" - ] - }, - "fine_tuned_model": { - "type": "string", - "nullable": true, - "description": "The name of the fine-tuned model that is being created. The value will be null if the fine-tuning job is still running." - }, - "finished_at": { - "type": "integer", - "nullable": true, - "description": "The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be null if the fine-tuning job is still running." - }, - "hyperparameters": { - "type": "object", - "description": "The hyperparameters used for the fine-tuning job. See the [fine-tuning guide](/docs/guides/fine-tuning) for more details.", - "properties": { - "n_epochs": { - "oneOf": [ - { - "type": "string", - "enum": [ - "auto" - ] - }, - { - "type": "integer", - "minimum": 1, - "maximum": 50 - } - ], - "default": "auto", - "description": "The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset.\n\"auto\" decides the optimal number of epochs based on the size of the dataset. If setting the number manually, we support any number between 1 and 50 epochs." - } - }, - "required": [ - "n_epochs" - ] - }, - "model": { - "type": "string", - "description": "The base model that is being fine-tuned." - }, - "object": { - "type": "string", - "description": "The object type, which is always \"fine_tuning.job\".", - "enum": [ - "fine_tuning.job" - ] - }, - "organization_id": { - "type": "string", - "description": "The organization that owns the fine-tuning job." - }, - "result_files": { - "type": "array", - "description": "The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the [Files API](/docs/api-reference/files/retrieve-contents).", - "items": { - "type": "string", - "example": "file-abc123" - } - }, - "status": { - "type": "string", - "description": "The current status of the fine-tuning job, which can be either `validating_files`, `queued`, `running`, `succeeded`, `failed`, or `cancelled`.", - "enum": [ - "validating_files", - "queued", - "running", - "succeeded", - "failed", - "cancelled" - ] - }, - "trained_tokens": { - "type": "integer", - "nullable": true, - "description": "The total number of billable tokens processed by this fine-tuning job. The value will be null if the fine-tuning job is still running." - }, - "training_file": { - "type": "string", - "description": "The file ID used for training. You can retrieve the training data with the [Files API](/docs/api-reference/files/retrieve-contents)." - }, - "validation_file": { - "type": "string", - "nullable": true, - "description": "The file ID used for validation. You can retrieve the validation results with the [Files API](/docs/api-reference/files/retrieve-contents)." - } - }, - "required": [ - "created_at", - "error", - "finished_at", - "fine_tuned_model", - "hyperparameters", - "id", - "model", - "object", - "organization_id", - "result_files", - "status", - "trained_tokens", - "training_file", - "validation_file" - ], - "x-oaiMeta": { - "name": "The fine-tuning job object", - "example": "{\n \"object\": \"fine_tuning.job\",\n \"id\": \"ftjob-abc123\",\n \"model\": \"davinci-002\",\n \"created_at\": 1692661014,\n \"finished_at\": 1692661190,\n \"fine_tuned_model\": \"ft:davinci-002:my-org:custom_suffix:7q8mpxmy\",\n \"organization_id\": \"org-123\",\n \"result_files\": [\n \"file-abc123\"\n ],\n \"status\": \"succeeded\",\n \"validation_file\": null,\n \"training_file\": \"file-abc123\",\n \"hyperparameters\": {\n \"n_epochs\": 4,\n },\n \"trained_tokens\": 5768\n}\n" - } - }, - "FineTuningJobEvent": { - "type": "object", - "description": "Fine-tuning job event object", - "properties": { - "id": { - "type": "string" - }, - "created_at": { - "type": "integer" - }, - "level": { - "type": "string", - "enum": [ - "info", - "warn", - "error" - ] - }, - "message": { - "type": "string" - }, - "object": { - "type": "string", - "enum": [ - "fine_tuning.job.event" - ] - } - }, - "required": [ - "id", - "object", - "created_at", - "level", - "message" - ], - "x-oaiMeta": { - "name": "The fine-tuning job event object", - "example": "{\n \"object\": \"fine_tuning.job.event\",\n \"id\": \"ftevent-abc123\"\n \"created_at\": 1677610602,\n \"level\": \"info\",\n \"message\": \"Created fine-tuning job\"\n}\n" - } - }, - "FineTune": { - "type": "object", - "deprecated": true, - "description": "The `FineTune` object represents a legacy fine-tune job that has been created through the API.\n", - "properties": { - "id": { - "type": "string", - "description": "The object identifier, which can be referenced in the API endpoints." - }, - "created_at": { - "type": "integer", - "description": "The Unix timestamp (in seconds) for when the fine-tuning job was created." - }, - "events": { - "type": "array", - "description": "The list of events that have been observed in the lifecycle of the FineTune job.", - "items": { - "$ref": "#/components/schemas/FineTuneEvent" - } - }, - "fine_tuned_model": { - "type": "string", - "nullable": true, - "description": "The name of the fine-tuned model that is being created." - }, - "hyperparams": { - "type": "object", - "description": "The hyperparameters used for the fine-tuning job. See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details.", - "properties": { - "batch_size": { - "type": "integer", - "description": "The batch size to use for training. The batch size is the number of\ntraining examples used to train a single forward and backward pass.\n" - }, - "classification_n_classes": { - "type": "integer", - "description": "The number of classes to use for computing classification metrics.\n" - }, - "classification_positive_class": { - "type": "string", - "description": "The positive class to use for computing classification metrics.\n" - }, - "compute_classification_metrics": { - "type": "boolean", - "description": "The classification metrics to compute using the validation dataset at the end of every epoch.\n" - }, - "learning_rate_multiplier": { - "type": "number", - "description": "The learning rate multiplier to use for training.\n" - }, - "n_epochs": { - "type": "integer", - "description": "The number of epochs to train the model for. An epoch refers to one\nfull cycle through the training dataset.\n" - }, - "prompt_loss_weight": { - "type": "number", - "description": "The weight to use for loss on the prompt tokens.\n" - } - }, - "required": [ - "batch_size", - "learning_rate_multiplier", - "n_epochs", - "prompt_loss_weight" - ] - }, - "model": { - "type": "string", - "description": "The base model that is being fine-tuned." - }, - "object": { - "type": "string", - "description": "The object type, which is always \"fine-tune\".", - "enum": [ - "fine-tune" - ] - }, - "organization_id": { - "type": "string", - "description": "The organization that owns the fine-tuning job." - }, - "result_files": { - "type": "array", - "description": "The compiled results files for the fine-tuning job.", - "items": { - "$ref": "#/components/schemas/OpenAIFile" - } - }, - "status": { - "type": "string", - "description": "The current status of the fine-tuning job, which can be either `created`, `running`, `succeeded`, `failed`, or `cancelled`." - }, - "training_files": { - "type": "array", - "description": "The list of files used for training.", - "items": { - "$ref": "#/components/schemas/OpenAIFile" - } - }, - "updated_at": { - "type": "integer", - "description": "The Unix timestamp (in seconds) for when the fine-tuning job was last updated." - }, - "validation_files": { - "type": "array", - "description": "The list of files used for validation.", - "items": { - "$ref": "#/components/schemas/OpenAIFile" - } - } - }, - "required": [ - "created_at", - "fine_tuned_model", - "hyperparams", - "id", - "model", - "object", - "organization_id", - "result_files", - "status", - "training_files", - "updated_at", - "validation_files" - ], - "x-oaiMeta": { - "name": "The fine-tune object", - "example": "{\n \"id\": \"ft-abc123\",\n \"object\": \"fine-tune\",\n \"model\": \"curie\",\n \"created_at\": 1614807352,\n \"events\": [\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807352,\n \"level\": \"info\",\n \"message\": \"Job enqueued. Waiting for jobs ahead to complete. Queue number: 0.\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807356,\n \"level\": \"info\",\n \"message\": \"Job started.\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807861,\n \"level\": \"info\",\n \"message\": \"Uploaded snapshot: curie:ft-acmeco-2021-03-03-21-44-20.\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807864,\n \"level\": \"info\",\n \"message\": \"Uploaded result files: file-abc123.\"\n },\n {\n \"object\": \"fine-tune-event\",\n \"created_at\": 1614807864,\n \"level\": \"info\",\n \"message\": \"Job succeeded.\"\n }\n ],\n \"fine_tuned_model\": \"curie:ft-acmeco-2021-03-03-21-44-20\",\n \"hyperparams\": {\n \"batch_size\": 4,\n \"learning_rate_multiplier\": 0.1,\n \"n_epochs\": 4,\n \"prompt_loss_weight\": 0.1,\n },\n \"organization_id\": \"org-123\",\n \"result_files\": [\n {\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"bytes\": 81509,\n \"created_at\": 1614807863,\n \"filename\": \"compiled_results.csv\",\n \"purpose\": \"fine-tune-results\"\n }\n ],\n \"status\": \"succeeded\",\n \"validation_files\": [],\n \"training_files\": [\n {\n \"id\": \"file-abc123\",\n \"object\": \"file\",\n \"bytes\": 1547276,\n \"created_at\": 1610062281,\n \"filename\": \"my-data-train.jsonl\",\n \"purpose\": \"fine-tune\"\n }\n ],\n \"updated_at\": 1614807865,\n}\n" - } - }, - "FineTuneEvent": { - "type": "object", - "deprecated": true, - "description": "Fine-tune event object", - "properties": { - "created_at": { - "type": "integer" - }, - "level": { - "type": "string" - }, - "message": { - "type": "string" - }, - "object": { - "type": "string", - "enum": [ - "fine-tune-event" - ] - } - }, - "required": [ - "object", - "created_at", - "level", - "message" - ], - "x-oaiMeta": { - "name": "The fine-tune event object", - "example": "{\n \"object\": \"fine-tune-event\",\n \"created_at\": 1677610602,\n \"level\": \"info\",\n \"message\": \"Created fine-tune job\"\n}\n" - } - }, - "CompletionUsage": { - "type": "object", - "description": "Usage statistics for the completion request.", - "properties": { - "completion_tokens": { - "type": "integer", - "description": "Number of tokens in the generated completion." - }, - "prompt_tokens": { - "type": "integer", - "description": "Number of tokens in the prompt." - }, - "total_tokens": { - "type": "integer", - "description": "Total number of tokens used in the request (prompt + completion)." - } - }, - "required": [ - "prompt_tokens", - "completion_tokens", - "total_tokens" - ] - }, - "AssistantObject": { - "type": "object", - "title": "Assistant", - "description": "Represents an `assistant` that can call the model and use tools.", - "properties": { - "id": { - "description": "The identifier, which can be referenced in API endpoints.", - "type": "string" - }, - "object": { - "description": "The object type, which is always `assistant`.", - "type": "string", - "enum": [ - "assistant" - ] - }, - "created_at": { - "description": "The Unix timestamp (in seconds) for when the assistant was created.", - "type": "integer" - }, - "name": { - "description": "The name of the assistant. The maximum length is 256 characters.\n", - "type": "string", - "maxLength": 256, - "nullable": true - }, - "description": { - "description": "The description of the assistant. The maximum length is 512 characters.\n", - "type": "string", - "maxLength": 512, - "nullable": true - }, - "model": { - "description": "ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them.\n", - "type": "string" - }, - "instructions": { - "description": "The system instructions that the assistant uses. The maximum length is 32768 characters.\n", - "type": "string", - "maxLength": 32768, - "nullable": true - }, - "tools": { - "description": "A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `retrieval`, or `function`.\n", - "default": [], - "type": "array", - "maxItems": 128, - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/AssistantToolsCode" - }, - { - "$ref": "#/components/schemas/AssistantToolsRetrieval" - }, - { - "$ref": "#/components/schemas/AssistantToolsFunction" - } - ], - "x-oaiExpandable": true - } - }, - "file_ids": { - "description": "A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a maximum of 20 files attached to the assistant. Files are ordered by their creation date in ascending order.\n", - "default": [], - "type": "array", - "maxItems": 20, - "items": { - "type": "string" - } - }, - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - }, - "required": [ - "id", - "object", - "created_at", - "name", - "description", - "model", - "instructions", - "tools", - "file_ids", - "metadata" - ], - "x-oaiMeta": { - "name": "The assistant object", - "beta": true, - "example": "{\n \"id\": \"asst_abc123\",\n \"object\": \"assistant\",\n \"created_at\": 1698984975,\n \"name\": \"Math Tutor\",\n \"description\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You are a personal math tutor. When asked a question, write and run Python code to answer the question.\",\n \"tools\": [\n {\n \"type\": \"code_interpreter\"\n }\n ],\n \"file_ids\": [],\n \"metadata\": {}\n}\n" - } - }, - "CreateAssistantRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "model": { - "description": "ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them.\n", - "anyOf": [ - { - "type": "string" - } - ] - }, - "name": { - "description": "The name of the assistant. The maximum length is 256 characters.\n", - "type": "string", - "nullable": true, - "maxLength": 256 - }, - "description": { - "description": "The description of the assistant. The maximum length is 512 characters.\n", - "type": "string", - "nullable": true, - "maxLength": 512 - }, - "instructions": { - "description": "The system instructions that the assistant uses. The maximum length is 32768 characters.\n", - "type": "string", - "nullable": true, - "maxLength": 32768 - }, - "tools": { - "description": "A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `retrieval`, or `function`.\n", - "default": [], - "type": "array", - "maxItems": 128, - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/AssistantToolsCode" - }, - { - "$ref": "#/components/schemas/AssistantToolsRetrieval" - }, - { - "$ref": "#/components/schemas/AssistantToolsFunction" - } - ], - "x-oaiExpandable": true - } - }, - "file_ids": { - "description": "A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a maximum of 20 files attached to the assistant. Files are ordered by their creation date in ascending order.\n", - "default": [], - "maxItems": 20, - "type": "array", - "items": { - "type": "string" - } - }, - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - }, - "required": [ - "model" - ] - }, - "ModifyAssistantRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "model": { - "description": "ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them.\n", - "anyOf": [ - { - "type": "string" - } - ] - }, - "name": { - "description": "The name of the assistant. The maximum length is 256 characters.\n", - "type": "string", - "nullable": true, - "maxLength": 256 - }, - "description": { - "description": "The description of the assistant. The maximum length is 512 characters.\n", - "type": "string", - "nullable": true, - "maxLength": 512 - }, - "instructions": { - "description": "The system instructions that the assistant uses. The maximum length is 32768 characters.\n", - "type": "string", - "nullable": true, - "maxLength": 32768 - }, - "tools": { - "description": "A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `retrieval`, or `function`.\n", - "default": [], - "type": "array", - "maxItems": 128, - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/AssistantToolsCode" - }, - { - "$ref": "#/components/schemas/AssistantToolsRetrieval" - }, - { - "$ref": "#/components/schemas/AssistantToolsFunction" - } - ], - "x-oaiExpandable": true - } - }, - "file_ids": { - "description": "A list of [File](/docs/api-reference/files) IDs attached to this assistant. There can be a maximum of 20 files attached to the assistant. Files are ordered by their creation date in ascending order. If a file was previously attached to the list but does not show up in the list, it will be deleted from the assistant.\n", - "default": [], - "type": "array", - "maxItems": 20, - "items": { - "type": "string" - } - }, - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - } - }, - "DeleteAssistantResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "deleted": { - "type": "boolean" - }, - "object": { - "type": "string", - "enum": [ - "assistant.deleted" - ] - } - }, - "required": [ - "id", - "object", - "deleted" - ] - }, - "ListAssistantsResponse": { - "type": "object", - "properties": { - "object": { - "type": "string", - "example": "list" - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AssistantObject" - } - }, - "first_id": { - "type": "string", - "example": "asst_abc123" - }, - "last_id": { - "type": "string", - "example": "asst_abc456" - }, - "has_more": { - "type": "boolean", - "example": false - } - }, - "required": [ - "object", - "data", - "first_id", - "last_id", - "has_more" - ], - "x-oaiMeta": { - "name": "List assistants response object", - "group": "chat", - "example": "{\n \"object\": \"list\",\n \"data\": [\n {\n \"id\": \"asst_abc123\",\n \"object\": \"assistant\",\n \"created_at\": 1698982736,\n \"name\": \"Coding Tutor\",\n \"description\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You are a helpful assistant designed to make me better at coding!\",\n \"tools\": [],\n \"file_ids\": [],\n \"metadata\": {}\n },\n {\n \"id\": \"asst_abc456\",\n \"object\": \"assistant\",\n \"created_at\": 1698982718,\n \"name\": \"My Assistant\",\n \"description\": null,\n \"model\": \"gpt-4\",\n \"instructions\": \"You are a helpful assistant designed to make me better at coding!\",\n \"tools\": [],\n \"file_ids\": [],\n \"metadata\": {}\n },\n {\n \"id\": \"asst_abc789\",\n \"object\": \"assistant\",\n \"created_at\": 1698982643,\n \"name\": null,\n \"description\": null,\n \"model\": \"gpt-4\",\n \"instructions\": null,\n \"tools\": [],\n \"file_ids\": [],\n \"metadata\": {}\n }\n ],\n \"first_id\": \"asst_abc123\",\n \"last_id\": \"asst_abc789\",\n \"has_more\": false\n}\n" - } - }, - "AssistantToolsCode": { - "type": "object", - "title": "Code interpreter tool", - "properties": { - "type": { - "type": "string", - "description": "The type of tool being defined: `code_interpreter`", - "enum": [ - "code_interpreter" - ] - } - }, - "required": [ - "type" - ] - }, - "AssistantToolsRetrieval": { - "type": "object", - "title": "Retrieval tool", - "properties": { - "type": { - "type": "string", - "description": "The type of tool being defined: `retrieval`", - "enum": [ - "retrieval" - ] - } - }, - "required": [ - "type" - ] - }, - "AssistantToolsFunction": { - "type": "object", - "title": "Function tool", - "properties": { - "type": { - "type": "string", - "description": "The type of tool being defined: `function`", - "enum": [ - "function" - ] - }, - "function": { - "$ref": "#/components/schemas/FunctionObject" - } - }, - "required": [ - "type", - "function" - ] - }, - "RunObject": { - "type": "object", - "title": "A run on a thread", - "description": "Represents an execution run on a [thread](/docs/api-reference/threads).", - "properties": { - "id": { - "description": "The identifier, which can be referenced in API endpoints.", - "type": "string" - }, - "object": { - "description": "The object type, which is always `thread.run`.", - "type": "string", - "enum": [ - "thread.run" - ] - }, - "created_at": { - "description": "The Unix timestamp (in seconds) for when the run was created.", - "type": "integer" - }, - "thread_id": { - "description": "The ID of the [thread](/docs/api-reference/threads) that was executed on as a part of this run.", - "type": "string" - }, - "assistant_id": { - "description": "The ID of the [assistant](/docs/api-reference/assistants) used for execution of this run.", - "type": "string" - }, - "status": { - "description": "The status of the run, which can be either `queued`, `in_progress`, `requires_action`, `cancelling`, `cancelled`, `failed`, `completed`, or `expired`.", - "type": "string", - "enum": [ - "queued", - "in_progress", - "requires_action", - "cancelling", - "cancelled", - "failed", - "completed", - "expired" - ] - }, - "required_action": { - "type": "object", - "description": "Details on the action required to continue the run. Will be `null` if no action is required.", - "nullable": true, - "properties": { - "type": { - "description": "For now, this is always `submit_tool_outputs`.", - "type": "string", - "enum": [ - "submit_tool_outputs" - ] - }, - "submit_tool_outputs": { - "type": "object", - "description": "Details on the tool outputs needed for this run to continue.", - "properties": { - "tool_calls": { - "type": "array", - "description": "A list of the relevant tool calls.", - "items": { - "$ref": "#/components/schemas/RunToolCallObject" - } - } - }, - "required": [ - "tool_calls" - ] - } - }, - "required": [ - "type", - "submit_tool_outputs" - ] - }, - "last_error": { - "type": "object", - "description": "The last error associated with this run. Will be `null` if there are no errors.", - "nullable": true, - "properties": { - "code": { - "type": "string", - "description": "One of `server_error` or `rate_limit_exceeded`.", - "enum": [ - "server_error", - "rate_limit_exceeded" - ] - }, - "message": { - "type": "string", - "description": "A human-readable description of the error." - } - }, - "required": [ - "code", - "message" - ] - }, - "expires_at": { - "description": "The Unix timestamp (in seconds) for when the run will expire.", - "type": "integer" - }, - "started_at": { - "description": "The Unix timestamp (in seconds) for when the run was started.", - "type": "integer", - "nullable": true - }, - "cancelled_at": { - "description": "The Unix timestamp (in seconds) for when the run was cancelled.", - "type": "integer", - "nullable": true - }, - "failed_at": { - "description": "The Unix timestamp (in seconds) for when the run failed.", - "type": "integer", - "nullable": true - }, - "completed_at": { - "description": "The Unix timestamp (in seconds) for when the run was completed.", - "type": "integer", - "nullable": true - }, - "model": { - "description": "The model that the [assistant](/docs/api-reference/assistants) used for this run.", - "type": "string" - }, - "instructions": { - "description": "The instructions that the [assistant](/docs/api-reference/assistants) used for this run.", - "type": "string" - }, - "tools": { - "description": "The list of tools that the [assistant](/docs/api-reference/assistants) used for this run.", - "default": [], - "type": "array", - "maxItems": 20, - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/AssistantToolsCode" - }, - { - "$ref": "#/components/schemas/AssistantToolsRetrieval" - }, - { - "$ref": "#/components/schemas/AssistantToolsFunction" - } - ], - "x-oaiExpandable": true - } - }, - "file_ids": { - "description": "The list of [File](/docs/api-reference/files) IDs the [assistant](/docs/api-reference/assistants) used for this run.", - "default": [], - "type": "array", - "items": { - "type": "string" - } - }, - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - }, - "required": [ - "id", - "object", - "created_at", - "thread_id", - "assistant_id", - "status", - "required_action", - "last_error", - "expires_at", - "started_at", - "cancelled_at", - "failed_at", - "completed_at", - "model", - "instructions", - "tools", - "file_ids", - "metadata" - ], - "x-oaiMeta": { - "name": "The run object", - "beta": true, - "example": "{\n \"id\": \"run_abc123\",\n \"object\": \"thread.run\",\n \"created_at\": 1698107661,\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"status\": \"completed\",\n \"started_at\": 1699073476,\n \"expires_at\": null,\n \"cancelled_at\": null,\n \"failed_at\": null,\n \"completed_at\": 1699073498,\n \"last_error\": null,\n \"model\": \"gpt-4\",\n \"instructions\": null,\n \"tools\": [{\"type\": \"retrieval\"}, {\"type\": \"code_interpreter\"}],\n \"file_ids\": [],\n \"metadata\": {}\n}\n" - } - }, - "CreateRunRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "assistant_id": { - "description": "The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run.", - "type": "string" - }, - "model": { - "description": "The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used.", - "type": "string", - "nullable": true - }, - "instructions": { - "description": "Overrides the [instructions](/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis.", - "type": "string", - "nullable": true - }, - "additional_instructions": { - "description": "Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions.", - "type": "string", - "nullable": true - }, - "tools": { - "description": "Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis.", - "nullable": true, - "type": "array", - "maxItems": 20, - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/AssistantToolsCode" - }, - { - "$ref": "#/components/schemas/AssistantToolsRetrieval" - }, - { - "$ref": "#/components/schemas/AssistantToolsFunction" - } - ], - "x-oaiExpandable": true - } - }, - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - }, - "required": [ - "thread_id", - "assistant_id" - ] - }, - "ListRunsResponse": { - "type": "object", - "properties": { - "object": { - "type": "string", - "example": "list" - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RunObject" - } - }, - "first_id": { - "type": "string", - "example": "run_abc123" - }, - "last_id": { - "type": "string", - "example": "run_abc456" - }, - "has_more": { - "type": "boolean", - "example": false - } - }, - "required": [ - "object", - "data", - "first_id", - "last_id", - "has_more" - ] - }, - "ModifyRunRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - } - }, - "SubmitToolOutputsRunRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "tool_outputs": { - "description": "A list of tools for which the outputs are being submitted.", - "type": "array", - "items": { - "type": "object", - "properties": { - "tool_call_id": { - "type": "string", - "description": "The ID of the tool call in the `required_action` object within the run object the output is being submitted for." - }, - "output": { - "type": "string", - "description": "The output of the tool call to be submitted to continue the run." - } - } - } - } - }, - "required": [ - "tool_outputs" - ] - }, - "RunToolCallObject": { - "type": "object", - "description": "Tool call objects", - "properties": { - "id": { - "type": "string", - "description": "The ID of the tool call. This ID must be referenced when you submit the tool outputs in using the [Submit tool outputs to run](/docs/api-reference/runs/submitToolOutputs) endpoint." - }, - "type": { - "type": "string", - "description": "The type of tool call the output is required for. For now, this is always `function`.", - "enum": [ - "function" - ] - }, - "function": { - "type": "object", - "description": "The function definition.", - "properties": { - "name": { - "type": "string", - "description": "The name of the function." - }, - "arguments": { - "type": "string", - "description": "The arguments that the model expects you to pass to the function." - } - }, - "required": [ - "name", - "arguments" - ] - } - }, - "required": [ - "id", - "type", - "function" - ] - }, - "CreateThreadAndRunRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "assistant_id": { - "description": "The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run.", - "type": "string" - }, - "thread": { - "$ref": "#/components/schemas/CreateThreadRequest", - "description": "If no thread is provided, an empty thread will be created." - }, - "model": { - "description": "The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used.", - "type": "string", - "nullable": true - }, - "instructions": { - "description": "Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis.", - "type": "string", - "nullable": true - }, - "tools": { - "description": "Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis.", - "nullable": true, - "type": "array", - "maxItems": 20, - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/AssistantToolsCode" - }, - { - "$ref": "#/components/schemas/AssistantToolsRetrieval" - }, - { - "$ref": "#/components/schemas/AssistantToolsFunction" - } - ] - } - }, - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - }, - "required": [ - "thread_id", - "assistant_id" - ] - }, - "ThreadObject": { - "type": "object", - "title": "Thread", - "description": "Represents a thread that contains [messages](/docs/api-reference/messages).", - "properties": { - "id": { - "description": "The identifier, which can be referenced in API endpoints.", - "type": "string" - }, - "object": { - "description": "The object type, which is always `thread`.", - "type": "string", - "enum": [ - "thread" - ] - }, - "created_at": { - "description": "The Unix timestamp (in seconds) for when the thread was created.", - "type": "integer" - }, - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - }, - "required": [ - "id", - "object", - "created_at", - "metadata" - ], - "x-oaiMeta": { - "name": "The thread object", - "beta": true, - "example": "{\n \"id\": \"thread_abc123\",\n \"object\": \"thread\",\n \"created_at\": 1698107661,\n \"metadata\": {}\n}\n" - } - }, - "CreateThreadRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "messages": { - "description": "A list of [messages](/docs/api-reference/messages) to start the thread with.", - "type": "array", - "items": { - "$ref": "#/components/schemas/CreateMessageRequest" - } - }, - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - } - }, - "ModifyThreadRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - } - }, - "DeleteThreadResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "deleted": { - "type": "boolean" - }, - "object": { - "type": "string", - "enum": [ - "thread.deleted" - ] - } - }, - "required": [ - "id", - "object", - "deleted" - ] - }, - "ListThreadsResponse": { - "properties": { - "object": { - "type": "string", - "example": "list" - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ThreadObject" - } - }, - "first_id": { - "type": "string", - "example": "asst_abc123" - }, - "last_id": { - "type": "string", - "example": "asst_abc456" - }, - "has_more": { - "type": "boolean", - "example": false - } - }, - "required": [ - "object", - "data", - "first_id", - "last_id", - "has_more" - ] - }, - "MessageObject": { - "type": "object", - "title": "The message object", - "description": "Represents a message within a [thread](/docs/api-reference/threads).", - "properties": { - "id": { - "description": "The identifier, which can be referenced in API endpoints.", - "type": "string" - }, - "object": { - "description": "The object type, which is always `thread.message`.", - "type": "string", - "enum": [ - "thread.message" - ] - }, - "created_at": { - "description": "The Unix timestamp (in seconds) for when the message was created.", - "type": "integer" - }, - "thread_id": { - "description": "The [thread](/docs/api-reference/threads) ID that this message belongs to.", - "type": "string" - }, - "role": { - "description": "The entity that produced the message. One of `user` or `assistant`.", - "type": "string", - "enum": [ - "user", - "assistant" - ] - }, - "content": { - "description": "The content of the message in array of text and/or images.", - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/MessageContentImageFileObject" - }, - { - "$ref": "#/components/schemas/MessageContentTextObject" - } - ], - "x-oaiExpandable": true - } - }, - "assistant_id": { - "description": "If applicable, the ID of the [assistant](/docs/api-reference/assistants) that authored this message.", - "type": "string", - "nullable": true - }, - "run_id": { - "description": "If applicable, the ID of the [run](/docs/api-reference/runs) associated with the authoring of this message.", - "type": "string", - "nullable": true - }, - "file_ids": { - "description": "A list of [file](/docs/api-reference/files) IDs that the assistant should use. Useful for tools like retrieval and code_interpreter that can access files. A maximum of 10 files can be attached to a message.", - "default": [], - "maxItems": 10, - "type": "array", - "items": { - "type": "string" - } - }, - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - }, - "required": [ - "id", - "object", - "created_at", - "thread_id", - "role", - "content", - "assistant_id", - "run_id", - "file_ids", - "metadata" - ], - "x-oaiMeta": { - "name": "The message object", - "beta": true, - "example": "{\n \"id\": \"msg_abc123\",\n \"object\": \"thread.message\",\n \"created_at\": 1698983503,\n \"thread_id\": \"thread_abc123\",\n \"role\": \"assistant\",\n \"content\": [\n {\n \"type\": \"text\",\n \"text\": {\n \"value\": \"Hi! How can I help you today?\",\n \"annotations\": []\n }\n }\n ],\n \"file_ids\": [],\n \"assistant_id\": \"asst_abc123\",\n \"run_id\": \"run_abc123\",\n \"metadata\": {}\n}\n" - } - }, - "CreateMessageRequest": { - "type": "object", - "additionalProperties": false, - "required": [ - "role", - "content" - ], - "properties": { - "role": { - "type": "string", - "enum": [ - "user" - ], - "description": "The role of the entity that is creating the message. Currently only `user` is supported." - }, - "content": { - "type": "string", - "minLength": 1, - "maxLength": 32768, - "description": "The content of the message." - }, - "file_ids": { - "description": "A list of [File](/docs/api-reference/files) IDs that the message should use. There can be a maximum of 10 files attached to a message. Useful for tools like `retrieval` and `code_interpreter` that can access and use files.", - "default": [], - "type": "array", - "minItems": 1, - "maxItems": 10, - "items": { - "type": "string" - } - }, - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - } - }, - "ModifyMessageRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - } - }, - "DeleteMessageResponse": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "deleted": { - "type": "boolean" - }, - "object": { - "type": "string", - "enum": [ - "thread.message.deleted" - ] - } - }, - "required": [ - "id", - "object", - "deleted" - ] - }, - "ListMessagesResponse": { - "properties": { - "object": { - "type": "string", - "example": "list" - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MessageObject" - } - }, - "first_id": { - "type": "string", - "example": "msg_abc123" - }, - "last_id": { - "type": "string", - "example": "msg_abc123" - }, - "has_more": { - "type": "boolean", - "example": false - } - }, - "required": [ - "object", - "data", - "first_id", - "last_id", - "has_more" - ] - }, - "MessageContentImageFileObject": { - "title": "Image file", - "type": "object", - "description": "References an image [File](/docs/api-reference/files) in the content of a message.", - "properties": { - "type": { - "description": "Always `image_file`.", - "type": "string", - "enum": [ - "image_file" - ] - }, - "image_file": { - "type": "object", - "properties": { - "file_id": { - "description": "The [File](/docs/api-reference/files) ID of the image in the message content.", - "type": "string" - } - }, - "required": [ - "file_id" - ] - } - }, - "required": [ - "type", - "image_file" - ] - }, - "MessageContentTextObject": { - "title": "Text", - "type": "object", - "description": "The text content that is part of a message.", - "properties": { - "type": { - "description": "Always `text`.", - "type": "string", - "enum": [ - "text" - ] - }, - "text": { - "type": "object", - "properties": { - "value": { - "description": "The data that makes up the text.", - "type": "string" - }, - "annotations": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/MessageContentTextAnnotationsFileCitationObject" - }, - { - "$ref": "#/components/schemas/MessageContentTextAnnotationsFilePathObject" - } - ], - "x-oaiExpandable": true - } - } - }, - "required": [ - "value", - "annotations" - ] - } - }, - "required": [ - "type", - "text" - ] - }, - "MessageContentTextAnnotationsFileCitationObject": { - "title": "File citation", - "type": "object", - "description": "A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the \"retrieval\" tool to search files.", - "properties": { - "type": { - "description": "Always `file_citation`.", - "type": "string", - "enum": [ - "file_citation" - ] - }, - "text": { - "description": "The text in the message content that needs to be replaced.", - "type": "string" - }, - "file_citation": { - "type": "object", - "properties": { - "file_id": { - "description": "The ID of the specific File the citation is from.", - "type": "string" - }, - "quote": { - "description": "The specific quote in the file.", - "type": "string" - } - }, - "required": [ - "file_id", - "quote" - ] - }, - "start_index": { - "type": "integer", - "minimum": 0 - }, - "end_index": { - "type": "integer", - "minimum": 0 - } - }, - "required": [ - "type", - "text", - "file_citation", - "start_index", - "end_index" - ] - }, - "MessageContentTextAnnotationsFilePathObject": { - "title": "File path", - "type": "object", - "description": "A URL for the file that's generated when the assistant used the `code_interpreter` tool to generate a file.", - "properties": { - "type": { - "description": "Always `file_path`.", - "type": "string", - "enum": [ - "file_path" - ] - }, - "text": { - "description": "The text in the message content that needs to be replaced.", - "type": "string" - }, - "file_path": { - "type": "object", - "properties": { - "file_id": { - "description": "The ID of the file that was generated.", - "type": "string" - } - }, - "required": [ - "file_id" - ] - }, - "start_index": { - "type": "integer", - "minimum": 0 - }, - "end_index": { - "type": "integer", - "minimum": 0 - } - }, - "required": [ - "type", - "text", - "file_path", - "start_index", - "end_index" - ] - }, - "RunStepObject": { - "type": "object", - "title": "Run steps", - "description": "Represents a step in execution of a run.\n", - "properties": { - "id": { - "description": "The identifier of the run step, which can be referenced in API endpoints.", - "type": "string" - }, - "object": { - "description": "The object type, which is always `thread.run.step`.", - "type": "string", - "enum": [ - "thread.run.step" - ] - }, - "created_at": { - "description": "The Unix timestamp (in seconds) for when the run step was created.", - "type": "integer" - }, - "assistant_id": { - "description": "The ID of the [assistant](/docs/api-reference/assistants) associated with the run step.", - "type": "string" - }, - "thread_id": { - "description": "The ID of the [thread](/docs/api-reference/threads) that was run.", - "type": "string" - }, - "run_id": { - "description": "The ID of the [run](/docs/api-reference/runs) that this run step is a part of.", - "type": "string" - }, - "type": { - "description": "The type of run step, which can be either `message_creation` or `tool_calls`.", - "type": "string", - "enum": [ - "message_creation", - "tool_calls" - ] - }, - "status": { - "description": "The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, `completed`, or `expired`.", - "type": "string", - "enum": [ - "in_progress", - "cancelled", - "failed", - "completed", - "expired" - ] - }, - "step_details": { - "type": "object", - "description": "The details of the run step.", - "oneOf": [ - { - "$ref": "#/components/schemas/RunStepDetailsMessageCreationObject" - }, - { - "$ref": "#/components/schemas/RunStepDetailsToolCallsObject" - } - ], - "x-oaiExpandable": true - }, - "last_error": { - "type": "object", - "description": "The last error associated with this run step. Will be `null` if there are no errors.", - "nullable": true, - "properties": { - "code": { - "type": "string", - "description": "One of `server_error` or `rate_limit_exceeded`.", - "enum": [ - "server_error", - "rate_limit_exceeded" - ] - }, - "message": { - "type": "string", - "description": "A human-readable description of the error." - } - }, - "required": [ - "code", - "message" - ] - }, - "expired_at": { - "description": "The Unix timestamp (in seconds) for when the run step expired. A step is considered expired if the parent run is expired.", - "type": "integer", - "nullable": true - }, - "cancelled_at": { - "description": "The Unix timestamp (in seconds) for when the run step was cancelled.", - "type": "integer", - "nullable": true - }, - "failed_at": { - "description": "The Unix timestamp (in seconds) for when the run step failed.", - "type": "integer", - "nullable": true - }, - "completed_at": { - "description": "The Unix timestamp (in seconds) for when the run step completed.", - "type": "integer", - "nullable": true - }, - "metadata": { - "description": "Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.\n", - "type": "object", - "x-oaiTypeLabel": "map", - "nullable": true - } - }, - "required": [ - "id", - "object", - "created_at", - "assistant_id", - "thread_id", - "run_id", - "type", - "status", - "step_details", - "last_error", - "expired_at", - "cancelled_at", - "failed_at", - "completed_at", - "metadata" - ], - "x-oaiMeta": { - "name": "The run step object", - "beta": true, - "example": "{\n \"id\": \"step_abc123\",\n \"object\": \"thread.run.step\",\n \"created_at\": 1699063291,\n \"run_id\": \"run_abc123\",\n \"assistant_id\": \"asst_abc123\",\n \"thread_id\": \"thread_abc123\",\n \"type\": \"message_creation\",\n \"status\": \"completed\",\n \"cancelled_at\": null,\n \"completed_at\": 1699063291,\n \"expired_at\": null,\n \"failed_at\": null,\n \"last_error\": null,\n \"step_details\": {\n \"type\": \"message_creation\",\n \"message_creation\": {\n \"message_id\": \"msg_abc123\"\n }\n }\n}\n" - } - }, - "ListRunStepsResponse": { - "properties": { - "object": { - "type": "string", - "example": "list" - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RunStepObject" - } - }, - "first_id": { - "type": "string", - "example": "step_abc123" - }, - "last_id": { - "type": "string", - "example": "step_abc456" - }, - "has_more": { - "type": "boolean", - "example": false - } - }, - "required": [ - "object", - "data", - "first_id", - "last_id", - "has_more" - ] - }, - "RunStepDetailsMessageCreationObject": { - "title": "Message creation", - "type": "object", - "description": "Details of the message creation by the run step.", - "properties": { - "type": { - "description": "Always `message_creation`.", - "type": "string", - "enum": [ - "message_creation" - ] - }, - "message_creation": { - "type": "object", - "properties": { - "message_id": { - "type": "string", - "description": "The ID of the message that was created by this run step." - } - }, - "required": [ - "message_id" - ] - } - }, - "required": [ - "type", - "message_creation" - ] - }, - "RunStepDetailsToolCallsObject": { - "title": "Tool calls", - "type": "object", - "description": "Details of the tool call.", - "properties": { - "type": { - "description": "Always `tool_calls`.", - "type": "string", - "enum": [ - "tool_calls" - ] - }, - "tool_calls": { - "type": "array", - "description": "An array of tool calls the run step was involved in. These can be associated with one of three types of tools: `code_interpreter`, `retrieval`, or `function`.\n", - "items": { - "type": "object", - "oneOf": [ - { - "$ref": "#/components/schemas/RunStepDetailsToolCallsCodeObject" - }, - { - "$ref": "#/components/schemas/RunStepDetailsToolCallsRetrievalObject" - }, - { - "$ref": "#/components/schemas/RunStepDetailsToolCallsFunctionObject" - } - ], - "x-oaiExpandable": true - } - } - }, - "required": [ - "type", - "tool_calls" - ] - }, - "RunStepDetailsToolCallsCodeObject": { - "title": "Code interpreter tool call", - "type": "object", - "description": "Details of the Code Interpreter tool call the run step was involved in.", - "properties": { - "id": { - "type": "string", - "description": "The ID of the tool call." - }, - "type": { - "type": "string", - "description": "The type of tool call. This is always going to be `code_interpreter` for this type of tool call.", - "enum": [ - "code_interpreter" - ] - }, - "code_interpreter": { - "type": "object", - "description": "The Code Interpreter tool call definition.", - "required": [ - "input", - "outputs" - ], - "properties": { - "input": { - "type": "string", - "description": "The input to the Code Interpreter tool call." - }, - "outputs": { - "type": "array", - "description": "The outputs from the Code Interpreter tool call. Code Interpreter can output one or more items, including text (`logs`) or images (`image`). Each of these are represented by a different object type.", - "items": { - "type": "object", - "oneOf": [ - { - "$ref": "#/components/schemas/RunStepDetailsToolCallsCodeOutputLogsObject" - }, - { - "$ref": "#/components/schemas/RunStepDetailsToolCallsCodeOutputImageObject" - } - ], - "x-oaiExpandable": true - } - } - } - } - }, - "required": [ - "id", - "type", - "code_interpreter" - ] - }, - "RunStepDetailsToolCallsCodeOutputLogsObject": { - "title": "Code interpreter log output", - "type": "object", - "description": "Text output from the Code Interpreter tool call as part of a run step.", - "properties": { - "type": { - "description": "Always `logs`.", - "type": "string", - "enum": [ - "logs" - ] - }, - "logs": { - "type": "string", - "description": "The text output from the Code Interpreter tool call." - } - }, - "required": [ - "type", - "logs" - ] - }, - "RunStepDetailsToolCallsCodeOutputImageObject": { - "title": "Code interpreter image output", - "type": "object", - "properties": { - "type": { - "description": "Always `image`.", - "type": "string", - "enum": [ - "image" - ] - }, - "image": { - "type": "object", - "properties": { - "file_id": { - "description": "The [file](/docs/api-reference/files) ID of the image.", - "type": "string" - } - }, - "required": [ - "file_id" - ] - } - }, - "required": [ - "type", - "image" - ] - }, - "RunStepDetailsToolCallsRetrievalObject": { - "title": "Retrieval tool call", - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "The ID of the tool call object." - }, - "type": { - "type": "string", - "description": "The type of tool call. This is always going to be `retrieval` for this type of tool call.", - "enum": [ - "retrieval" - ] - }, - "retrieval": { - "type": "object", - "description": "For now, this is always going to be an empty object.", - "x-oaiTypeLabel": "map" - } - }, - "required": [ - "id", - "type", - "retrieval" - ] - }, - "RunStepDetailsToolCallsFunctionObject": { - "type": "object", - "title": "Function tool call", - "properties": { - "id": { - "type": "string", - "description": "The ID of the tool call object." - }, - "type": { - "type": "string", - "description": "The type of tool call. This is always going to be `function` for this type of tool call.", - "enum": [ - "function" - ] - }, - "function": { - "type": "object", - "description": "The definition of the function that was called.", - "properties": { - "name": { - "type": "string", - "description": "The name of the function." - }, - "arguments": { - "type": "string", - "description": "The arguments passed to the function." - }, - "output": { - "type": "string", - "description": "The output of the function. This will be `null` if the outputs have not been [submitted](/docs/api-reference/runs/submitToolOutputs) yet.", - "nullable": true - } - }, - "required": [ - "name", - "arguments", - "output" - ] - } - }, - "required": [ - "id", - "type", - "function" - ] - }, - "AssistantFileObject": { - "type": "object", - "title": "Assistant files", - "description": "A list of [Files](/docs/api-reference/files) attached to an `assistant`.", - "properties": { - "id": { - "description": "The identifier, which can be referenced in API endpoints.", - "type": "string" - }, - "object": { - "description": "The object type, which is always `assistant.file`.", - "type": "string", - "enum": [ - "assistant.file" - ] - }, - "created_at": { - "description": "The Unix timestamp (in seconds) for when the assistant file was created.", - "type": "integer" - }, - "assistant_id": { - "description": "The assistant ID that the file is attached to.", - "type": "string" - } - }, - "required": [ - "id", - "object", - "created_at", - "assistant_id" - ], - "x-oaiMeta": { - "name": "The assistant file object", - "beta": true, - "example": "{\n \"id\": \"file-abc123\",\n \"object\": \"assistant.file\",\n \"created_at\": 1699055364,\n \"assistant_id\": \"asst_abc123\"\n}\n" - } - }, - "CreateAssistantFileRequest": { - "type": "object", - "additionalProperties": false, - "properties": { - "file_id": { - "description": "A [File](/docs/api-reference/files) ID (with `purpose=\"assistants\"`) that the assistant should use. Useful for tools like `retrieval` and `code_interpreter` that can access files.", - "type": "string" - } - }, - "required": [ - "file_id" - ] - }, - "DeleteAssistantFileResponse": { - "type": "object", - "description": "Deletes the association between the assistant and the file, but does not delete the [File](/docs/api-reference/files) object itself.", - "properties": { - "id": { - "type": "string" - }, - "deleted": { - "type": "boolean" - }, - "object": { - "type": "string", - "enum": [ - "assistant.file.deleted" - ] - } - }, - "required": [ - "id", - "object", - "deleted" - ] - }, - "ListAssistantFilesResponse": { - "properties": { - "object": { - "type": "string", - "example": "list" - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AssistantFileObject" - } - }, - "first_id": { - "type": "string", - "example": "file-abc123" - }, - "last_id": { - "type": "string", - "example": "file-abc456" - }, - "has_more": { - "type": "boolean", - "example": false - } - }, - "required": [ - "object", - "data", - "items", - "first_id", - "last_id", - "has_more" - ] - }, - "MessageFileObject": { - "type": "object", - "title": "Message files", - "description": "A list of files attached to a `message`.", - "properties": { - "id": { - "description": "The identifier, which can be referenced in API endpoints.", - "type": "string" - }, - "object": { - "description": "The object type, which is always `thread.message.file`.", - "type": "string", - "enum": [ - "thread.message.file" - ] - }, - "created_at": { - "description": "The Unix timestamp (in seconds) for when the message file was created.", - "type": "integer" - }, - "message_id": { - "description": "The ID of the [message](/docs/api-reference/messages) that the [File](/docs/api-reference/files) is attached to.", - "type": "string" - } - }, - "required": [ - "id", - "object", - "created_at", - "message_id" - ], - "x-oaiMeta": { - "name": "The message file object", - "beta": true, - "example": "{\n \"id\": \"file-abc123\",\n \"object\": \"thread.message.file\",\n \"created_at\": 1698107661,\n \"message_id\": \"message_QLoItBbqwyAJEzlTy4y9kOMM\",\n \"file_id\": \"file-abc123\"\n}\n" - } - }, - "ListMessageFilesResponse": { - "properties": { - "object": { - "type": "string", - "example": "list" - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MessageFileObject" - } - }, - "first_id": { - "type": "string", - "example": "file-abc123" - }, - "last_id": { - "type": "string", - "example": "file-abc456" - }, - "has_more": { - "type": "boolean", - "example": false - } - }, - "required": [ - "object", - "data", - "items", - "first_id", - "last_id", - "has_more" - ] - } - } - }, - "security": [ - { - "ApiKeyAuth": [] - } - ], - "x-oaiMeta": { - "groups": [ - { - "id": "audio", - "title": "Audio", - "description": "Learn how to turn audio into text or text into audio.\n\nRelated guide: [Speech to text](/docs/guides/speech-to-text)\n", - "sections": [ - { - "type": "endpoint", - "key": "createSpeech", - "path": "createSpeech" - }, - { - "type": "endpoint", - "key": "createTranscription", - "path": "createTranscription" - }, - { - "type": "endpoint", - "key": "createTranslation", - "path": "createTranslation" - } - ] - }, - { - "id": "chat", - "title": "Chat", - "description": "Given a list of messages comprising a conversation, the model will return a response.\n\nRelated guide: [Chat Completions](/docs/guides/text-generation)\n", - "sections": [ - { - "type": "object", - "key": "CreateChatCompletionResponse", - "path": "object" - }, - { - "type": "object", - "key": "CreateChatCompletionStreamResponse", - "path": "streaming" - }, - { - "type": "endpoint", - "key": "createChatCompletion", - "path": "create" - } - ] - }, - { - "id": "embeddings", - "title": "Embeddings", - "description": "Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms.\n\nRelated guide: [Embeddings](/docs/guides/embeddings)\n", - "sections": [ - { - "type": "object", - "key": "Embedding", - "path": "object" - }, - { - "type": "endpoint", - "key": "createEmbedding", - "path": "create" - } - ] - }, - { - "id": "fine-tuning", - "title": "Fine-tuning", - "description": "Manage fine-tuning jobs to tailor a model to your specific training data.\n\nRelated guide: [Fine-tune models](/docs/guides/fine-tuning)\n", - "sections": [ - { - "type": "object", - "key": "FineTuningJob", - "path": "object" - }, - { - "type": "endpoint", - "key": "createFineTuningJob", - "path": "create" - }, - { - "type": "endpoint", - "key": "listPaginatedFineTuningJobs", - "path": "list" - }, - { - "type": "endpoint", - "key": "retrieveFineTuningJob", - "path": "retrieve" - }, - { - "type": "endpoint", - "key": "cancelFineTuningJob", - "path": "cancel" - }, - { - "type": "object", - "key": "FineTuningJobEvent", - "path": "event-object" - }, - { - "type": "endpoint", - "key": "listFineTuningEvents", - "path": "list-events" - } - ] - }, - { - "id": "files", - "title": "Files", - "description": "Files are used to upload documents that can be used with features like [Assistants](/docs/api-reference/assistants) and [Fine-tuning](/docs/api-reference/fine-tuning).\n", - "sections": [ - { - "type": "object", - "key": "OpenAIFile", - "path": "object" - }, - { - "type": "endpoint", - "key": "listFiles", - "path": "list" - }, - { - "type": "endpoint", - "key": "createFile", - "path": "create" - }, - { - "type": "endpoint", - "key": "deleteFile", - "path": "delete" - }, - { - "type": "endpoint", - "key": "retrieveFile", - "path": "retrieve" - }, - { - "type": "endpoint", - "key": "downloadFile", - "path": "retrieve-contents" - } - ] - }, - { - "id": "images", - "title": "Images", - "description": "Given a prompt and/or an input image, the model will generate a new image.\n\nRelated guide: [Image generation](/docs/guides/images)\n", - "sections": [ - { - "type": "object", - "key": "Image", - "path": "object" - }, - { - "type": "endpoint", - "key": "createImage", - "path": "create" - }, - { - "type": "endpoint", - "key": "createImageEdit", - "path": "createEdit" - }, - { - "type": "endpoint", - "key": "createImageVariation", - "path": "createVariation" - } - ] - }, - { - "id": "models", - "title": "Models", - "description": "List and describe the various models available in the API. You can refer to the [Models](/docs/models) documentation to understand what models are available and the differences between them.\n", - "sections": [ - { - "type": "object", - "key": "Model", - "path": "object" - }, - { - "type": "endpoint", - "key": "listModels", - "path": "list" - }, - { - "type": "endpoint", - "key": "retrieveModel", - "path": "retrieve" - }, - { - "type": "endpoint", - "key": "deleteModel", - "path": "delete" - } - ] - }, - { - "id": "moderations", - "title": "Moderations", - "description": "Given a input text, outputs if the model classifies it as violating OpenAI's content policy.\n\nRelated guide: [Moderations](/docs/guides/moderation)\n", - "sections": [ - { - "type": "object", - "key": "CreateModerationResponse", - "path": "object" - }, - { - "type": "endpoint", - "key": "createModeration", - "path": "create" - } - ] - }, - { - "id": "assistants", - "title": "Assistants", - "beta": true, - "description": "Build assistants that can call models and use tools to perform tasks.\n\n[Get started with the Assistants API](/docs/assistants)\n", - "sections": [ - { - "type": "object", - "key": "AssistantObject", - "path": "object" - }, - { - "type": "endpoint", - "key": "createAssistant", - "path": "createAssistant" - }, - { - "type": "endpoint", - "key": "getAssistant", - "path": "getAssistant" - }, - { - "type": "endpoint", - "key": "modifyAssistant", - "path": "modifyAssistant" - }, - { - "type": "endpoint", - "key": "deleteAssistant", - "path": "deleteAssistant" - }, - { - "type": "endpoint", - "key": "listAssistants", - "path": "listAssistants" - }, - { - "type": "object", - "key": "AssistantFileObject", - "path": "file-object" - }, - { - "type": "endpoint", - "key": "createAssistantFile", - "path": "createAssistantFile" - }, - { - "type": "endpoint", - "key": "getAssistantFile", - "path": "getAssistantFile" - }, - { - "type": "endpoint", - "key": "deleteAssistantFile", - "path": "deleteAssistantFile" - }, - { - "type": "endpoint", - "key": "listAssistantFiles", - "path": "listAssistantFiles" - } - ] - }, - { - "id": "threads", - "title": "Threads", - "beta": true, - "description": "Create threads that assistants can interact with.\n\nRelated guide: [Assistants](/docs/assistants/overview)\n", - "sections": [ - { - "type": "object", - "key": "ThreadObject", - "path": "object" - }, - { - "type": "endpoint", - "key": "createThread", - "path": "createThread" - }, - { - "type": "endpoint", - "key": "getThread", - "path": "getThread" - }, - { - "type": "endpoint", - "key": "modifyThread", - "path": "modifyThread" - }, - { - "type": "endpoint", - "key": "deleteThread", - "path": "deleteThread" - } - ] - }, - { - "id": "messages", - "title": "Messages", - "beta": true, - "description": "Create messages within threads\n\nRelated guide: [Assistants](/docs/assistants/overview)\n", - "sections": [ - { - "type": "object", - "key": "MessageObject", - "path": "object" - }, - { - "type": "endpoint", - "key": "createMessage", - "path": "createMessage" - }, - { - "type": "endpoint", - "key": "getMessage", - "path": "getMessage" - }, - { - "type": "endpoint", - "key": "modifyMessage", - "path": "modifyMessage" - }, - { - "type": "endpoint", - "key": "listMessages", - "path": "listMessages" - }, - { - "type": "object", - "key": "MessageFileObject", - "path": "file-object" - }, - { - "type": "endpoint", - "key": "getMessageFile", - "path": "getMessageFile" - }, - { - "type": "endpoint", - "key": "listMessageFiles", - "path": "listMessageFiles" - } - ] - }, - { - "id": "runs", - "title": "Runs", - "beta": true, - "description": "Represents an execution run on a thread.\n\nRelated guide: [Assistants](/docs/assistants/overview)\n", - "sections": [ - { - "type": "object", - "key": "RunObject", - "path": "object" - }, - { - "type": "endpoint", - "key": "createRun", - "path": "createRun" - }, - { - "type": "endpoint", - "key": "getRun", - "path": "getRun" - }, - { - "type": "endpoint", - "key": "modifyRun", - "path": "modifyRun" - }, - { - "type": "endpoint", - "key": "listRuns", - "path": "listRuns" - }, - { - "type": "endpoint", - "key": "submitToolOuputsToRun", - "path": "submitToolOutputs" - }, - { - "type": "endpoint", - "key": "cancelRun", - "path": "cancelRun" - }, - { - "type": "endpoint", - "key": "createThreadAndRun", - "path": "createThreadAndRun" - }, - { - "type": "object", - "key": "RunStepObject", - "path": "step-object" - }, - { - "type": "endpoint", - "key": "getRunStep", - "path": "getRunStep" - }, - { - "type": "endpoint", - "key": "listRunSteps", - "path": "listRunSteps" - } - ] - }, - { - "id": "completions", - "title": "Completions", - "legacy": true, - "description": "Given a prompt, the model will return one or more predicted completions along with the probabilities of alternative tokens at each position. Most developer should use our [Chat Completions API](/docs/guides/text-generation/text-generation-models) to leverage our best and newest models. Most models that support the legacy Completions endpoint [will be shut off on January 4th, 2024](/docs/deprecations/2023-07-06-gpt-and-embeddings).\n", - "sections": [ - { - "type": "object", - "key": "CreateCompletionResponse", - "path": "object" - }, - { - "type": "endpoint", - "key": "createCompletion", - "path": "create" - } - ] - }, - { - "id": "edits", - "title": "Edits", - "deprecated": true, - "description": "Given a prompt and an instruction, the model will return an edited version of the prompt. The Edits endpoint is deprecated will be [shut off on January 4th, 2024](/docs/deprecations/edit-models-endpoint).\n", - "sections": [ - { - "type": "object", - "key": "CreateEditResponse", - "path": "object" - }, - { - "type": "endpoint", - "key": "createEdit", - "path": "create" - } - ] - }, - { - "id": "fine-tunes", - "title": "Fine-tunes", - "deprecated": true, - "description": "Manage fine-tuning jobs to tailor a model to your specific training data. The [updated Fine-tuning endpoint](/docs/guides/fine-tuning) offers more capabilites and newer models.\n\nThe Fine-tunes endpoint will be [shut off on January 4th, 2024](/docs/deprecations/2023-08-22-fine-tunes-endpoint).\n", - "sections": [ - { - "type": "object", - "key": "FineTune", - "path": "object" - }, - { - "type": "endpoint", - "key": "createFineTune", - "path": "create" - }, - { - "type": "endpoint", - "key": "listFineTunes", - "path": "list" - }, - { - "type": "endpoint", - "key": "retrieveFineTune", - "path": "retrieve" - }, - { - "type": "endpoint", - "key": "cancelFineTune", - "path": "cancel" - }, - { - "type": "object", - "key": "FineTuneEvent", - "path": "event-object" - }, - { - "type": "endpoint", - "key": "listFineTuneEvents", - "path": "list-events" - } - ] - } - ] - } -} \ No newline at end of file diff --git a/boards/tools/openapi/tests/xkcd.js b/boards/tools/openapi/tests/xkcd.js deleted file mode 100644 index c53f3e33d66..00000000000 --- a/boards/tools/openapi/tests/xkcd.js +++ /dev/null @@ -1,20 +0,0 @@ -import { base, board, code } from "@google-labs/breadboard"; -import { core } from "@google-labs/core-kit"; - -const metaData = { - title: "Query the XKCD API via an Open API Spec board", - description: "Query's the XCD API.", - version: "0.0.3", -}; - -export default await board(() => { - const input = base.input({ $id: "input" }); - - const apiBoard = core.invoke({ - $id: "xkcdInvoke", - path: "../index.json", - url: input.url, - }); - - return core.invoke({}).in({ board: apiBoard.getInfo0json }); -}).serialize(metaData); diff --git a/boards/tools/openapi/tests/xkcd.json b/boards/tools/openapi/tests/xkcd.json deleted file mode 100644 index 5988753a033..00000000000 --- a/boards/tools/openapi/tests/xkcd.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "title": "Query the XKCD API via an Open API Spec board", - "description": "Query's the XCD API.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.1.0/packages/schema/breadboard.schema.json", - "version": "0.0.3", - "edges": [ - { - "from": "invoke-3", - "to": "output-2", - "out": "*", - "in": "" - }, - { - "from": "xkcdInvoke", - "to": "invoke-3", - "out": "getInfo0json", - "in": "board" - }, - { - "from": "input", - "to": "xkcdInvoke", - "out": "url", - "in": "url" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": {} - }, - { - "id": "invoke-3", - "type": "invoke", - "configuration": {} - }, - { - "id": "xkcdInvoke", - "type": "invoke", - "configuration": { - "path": "../index.json" - } - }, - { - "id": "input", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "url": { - "type": "string", - "title": "url" - } - }, - "required": [ - "url" - ] - } - } - } - ], - "kits": [], - "graphs": {} -} \ No newline at end of file diff --git a/core/tsconfig/CHANGELOG.md b/core/tsconfig/CHANGELOG.md new file mode 100644 index 00000000000..c5e4e21b1f6 --- /dev/null +++ b/core/tsconfig/CHANGELOG.md @@ -0,0 +1,7 @@ +# @google-labs/tsconfig + +## 0.0.2 + +### Patch Changes + +- 5496e6c: Migrate demo to particles-ui diff --git a/core/tsconfig/base.json b/core/tsconfig/base.json index 009a618bfa2..5c59aebac7b 100644 --- a/core/tsconfig/base.json +++ b/core/tsconfig/base.json @@ -8,7 +8,7 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "inlineSources": false, - "lib": ["ES2022", "DOM"], + "lib": ["ES2022", "DOM", "ES2023", "ES2024"], "module": "NodeNext", "target": "ES2022", "isolatedModules": true, diff --git a/core/tsconfig/package.json b/core/tsconfig/package.json index 827b357003f..64364b013a4 100644 --- a/core/tsconfig/package.json +++ b/core/tsconfig/package.json @@ -4,6 +4,6 @@ "registry": "https://wombat-dressing-room.appspot.com" }, "description": "Repo-specific configuration for all TypeScript projects", - "version": "0.0.1", + "version": "0.0.2", "private": true } diff --git a/docs/updates.json b/docs/updates.json new file mode 100644 index 00000000000..1e0c5d01a39 --- /dev/null +++ b/docs/updates.json @@ -0,0 +1,47 @@ +[ + { + "date": "2025-10-07", + "type": "info", + "text": "All systems green. If you see any problems with quota, please use the \"Send feedback\" link in the gear menu." + }, + { + "date": "2025-10-07", + "type": "warning", + "text": "Using the \"Gemini 2.5 Flash Image\" model will fail for a little bit. If you see errors generating images, switch to use \"Imagen 4\" instead." + }, + { + "date": "2025-09-08", + "type": "info", + "text": "All systems green. If you see any problems with quota, please use the \"Send feedback\" link in the gear menu." + }, + { + "date": "2025-09-07", + "type": "warning", + "text": "Using the \"Imagen 4\" model will fail for a little bit. If you see errors generating images, switch to \"Gemini 2.5 Flash Image\" instead." + }, + { + "date": "2025-08-28", + "type": "info", + "text": "The capacity issues have been resolved. All systems green. If you see any problems with quota, please use the \"Send feedback\" link in the gear menu." + }, + { + "date": "2025-08-27", + "type": "warning", + "text": "We are currently experiencing capacity issues with Gemini 2.5 Pro model. If you see \"Quota Exhausted\" error, change your steps to use Gemini 2.5 Flash." + }, + { + "date": "2025-07-30", + "type": "info", + "text": "All systems are green and if you see any problems with quota, please use the \"Send feedback\" link in the gear menu." + }, + { + "date": "2025-07-29", + "type": "warning", + "text": "The Lyria 2 model calls appear to be failing with longer prompts. For now, try to keep your Lyria prompts short." + }, + { + "date": "2025-07-25", + "type": "info", + "text": "Welcome to Opal! We're very experimental and apologize in advance all the construction debris: we wanted to have you over as early as possible to help us grow it into something you love." + } +] diff --git a/example-boards/examples/my-board.bgl.json b/example-boards/examples/my-board.bgl.json deleted file mode 100644 index 82b7866c9de..00000000000 --- a/example-boards/examples/my-board.bgl.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "title": "Blank board", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "metadata": { - "comments": [] - }, - "edges": [ - { - "from": "input", - "out": "context", - "to": "output", - "in": "context" - } - ], - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 0, - "y": 0, - "collapsed": true - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "null" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 173, - "y": 0, - "collapsed": true - } - } - } - ] -} diff --git a/experiments/agent/.gitignore b/experiments/agent/.gitignore new file mode 100644 index 00000000000..466e24805a9 --- /dev/null +++ b/experiments/agent/.gitignore @@ -0,0 +1 @@ +out/ \ No newline at end of file diff --git a/experiments/agent/README.md b/experiments/agent/README.md new file mode 100644 index 00000000000..4be3af0f6b8 --- /dev/null +++ b/experiments/agent/README.md @@ -0,0 +1,97 @@ +# The Agent Experiment + +**Key insight 1**: Use a closed-loop setup, where Gemini is constrained to +predicting function calls only, and use a small set of functions (aks "system +functions") to drive the control flow. + +The following system functions emerged through the experiment: + +- `system_objective_fulfilled` -- terminates the loop, a way for Gemini to + declare victory. + +- `system_failed_to_fulfill_objective` -- terminates the loop, a way for Gemini + to admit defeat. + +- `system_request_user_input` -- requests input from a user. Unlike the typical + open loop, we only let Gemini chat with the user through this function. This + has an additional benefit of enabling structured UI: currently, the function + allows Gemini to specify the type of input. We can look into the future and + imagine that the function argument is the A2UI or some A2UI pidgin that + literally draws consistent UI. + +With these three functions, the agent is able to act as the typical open-loop +setup, but with a lot more consistent function-calling performance. + +**Key insight 2**: Introduce a virtual file system (VFS), where the agent +operates on the handles to files, but not the actual data. This is a departure +of the classic Gemini setup, where the files are mixed in as `inlineData` or +`fileData` parts, and it allows for a much nicer passing of the files around +across functions and the agent. + +In particular, when the agent fulfills its objective, it outputs three distinct +chunks: + +- the user message -- a brief message to the user indicating success +- the actual outcome -- zero or more VFS handles +- intermediate results -- zero or more VFS handles all the files generated while + fulfilling the objective. + +This separation of what is shown to user and what is passed on to the next agent +creates a much smoother experience, because the outcome is not diluted with user +messaging, and the user messaging is not burdened with the files. Additionally, +the intermediate results can be used by the next agent as additional context. + +Gemini seems to be most comfortable using the XML-like construct +`` as the representation of the handle, reliably interpreting +it and even using it when interacting with the user. + +The additional system function was introduced to allow agent to write its output +to file: + +- `system_write_text_to_file` -- writes text into a file. This proven to be + useful for situations where the agent generates text and needs to pass it as + the outcome. + +**Key Insight 3**: Use hyperlinks for control transfer. Since XML/HTML tags +appear to be quite comforting to Gemini, hyperlinks were introduced as a slight +leap of faith. + +A hyperlink denotes the presence of another agent (peer agent) in the larger +system, and the agent is allowed to pass control to any of the agents that are +specified in the objective as hyperlinks. + +For example: + +```md +Ask the user (a middle schooler) about how they would like to learn today. Offer +them these choices and take them to the one they choose: + +- Fun Learning Game +- Educational Cartoon +- Engaging Interactive Lesson +``` + +A mental model: there's a URL space full of agents, with the `"/"` as the root +agent. By default, the success or failure functions transfer control to the root +agent. However, if the objective includes hyperlinks to other agents, our agent +has the option to pass control to them. + +This enables fairly complex routing scenarios, and Gemini seems to grok this +mental model quite well. + +## Experimenting + +Create `.env` file with `GEMINI_API_KEY`. + +Run + +```sh +npm run dev +``` + +The evals are in [src/eval-set.ts](src/eval-set.ts). To pick a different eval, +change the id in [src/index.ts](src/index.ts): + +```ts +const objective = evalSet.get("valid-eval-id-goes-here"); +``` diff --git a/experiments/agent/files/drop.png b/experiments/agent/files/drop.png new file mode 100644 index 00000000000..cce14b6bb06 Binary files /dev/null and b/experiments/agent/files/drop.png differ diff --git a/experiments/agent/files/rectangle.png b/experiments/agent/files/rectangle.png new file mode 100644 index 00000000000..c97bfcb62eb Binary files /dev/null and b/experiments/agent/files/rectangle.png differ diff --git a/experiments/agent/package.json b/experiments/agent/package.json new file mode 100644 index 00000000000..f54ceca322a --- /dev/null +++ b/experiments/agent/package.json @@ -0,0 +1,24 @@ +{ + "name": "vfs", + "private": true, + "version": "1.0.0", + "type": "module", + "main": "index.js", + "scripts": { + "dev": "tsx src/index.ts" + }, + "keywords": [], + "author": "", + "license": "Apache-2.0", + "description": "", + "dependencies": { + "@google/genai": "^1.27.0", + "dotenv": "^17.2.3", + "mime": "^4.1.0", + "zod": "^3.24.1", + "zod-to-json-schema": "^3.24.6" + }, + "devDependencies": { + "tsx": "^4.20.6" + } +} diff --git a/experiments/agent/src/a2ui.ts b/experiments/agent/src/a2ui.ts new file mode 100644 index 00000000000..e4b716c32e8 --- /dev/null +++ b/experiments/agent/src/a2ui.ts @@ -0,0 +1,537 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export { uiSchema, examples, uiSchemaLite }; + +const EXAMPLES = [ + "If the content is predominantly visual media (images and videos) then arrange them in a neat grid using Rows, Columns, and Lists. Try to put a few items on each row and try to make sure the grid is balanced. Put any other content, including text and audio, below the media. If there is a title, place it at the top.", + "If there are two or more pieces of visual media (images and videos) then give them priority and place them in a Row at the top with everything else underneath in a List. If there is a title, place it at the top.", + "If there is one piece of visual media (image or video), place it to the left, and put everything else to the right in a List. Within the list prioritize audio.If there is a title, place it at the top.", + "If all else fails and nothing matches the above examples, stack everything up in a vertical List in the order you find them. If there is a title, place it at the top.", +]; + +const examples = `Here are some example layouts which you can use. Do your best +to match these given the content you're working with: ${EXAMPLES.map( + (description) => { + return `- "${description}"\n`; + } +)}`; + +const uiSchema = { + description: + "Describes a JSON payload for an A2UI message, which is used to dynamically construct and update user interfaces. A message MUST contain a 'surfaceId' and exactly ONE of the action properties: 'beginRendering', 'surfaceUpdate', 'dataModelUpdate', or 'surfaceDeletion'.", + type: "object", + properties: { + surfaceId: { + type: "string", + description: + "The unique identifier for the UI surface this message applies to.", + }, + beginRendering: { + type: "object", + description: + "Signals the client to begin rendering a surface with a root component and specific styles.", + properties: { + root: { + type: "string", + description: "The ID of the root component to render.", + }, + styles: { + type: "object", + description: "Styling information for the UI.", + properties: { + font: { + type: "string", + description: "The primary font for the UI.", + }, + logoUrl: { + type: "string", + description: "A URL for the logo image.", + }, + primaryColor: { + type: "string", + description: + "The primary UI color as a hexadecimal code (e.g., '#00BFFF').", + }, + }, + }, + }, + required: ["root"], + }, + surfaceUpdate: { + type: "object", + description: "Updates a surface with a new set of components.", + properties: { + components: { + type: "array", + description: "A list containing all UI components for the surface.", + items: { + type: "object", + properties: { + id: { + type: "string", + description: "The unique identifier for this component.", + }, + component: { + type: "object", + description: + "A wrapper object that MUST contain exactly one key, which is the name of the component type (e.g., 'Heading'). The value is an object containing the properties for that specific component.", + properties: { + Heading: { + type: "object", + properties: { + text: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + level: { + type: "string", + enum: ["1", "2", "3", "4", "5"], + }, + }, + required: ["text"], + }, + Text: { + type: "object", + properties: { + text: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + }, + required: ["text"], + }, + Image: { + type: "object", + properties: { + url: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + fit: { + type: "string", + enum: [ + "fill", + "cover", + "contain", + "none", + "scale-down", + ], + }, + }, + required: ["url"], + }, + Video: { + type: "object", + properties: { + url: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + }, + required: ["url"], + }, + AudioPlayer: { + type: "object", + properties: { + url: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + description: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + }, + required: ["url"], + }, + Row: { + type: "object", + properties: { + children: { + type: "object", + description: + "Defines the children. Use 'explicitList' for a fixed set of children, or 'template' to generate children from a data list.", + properties: { + explicitList: { + type: "array", + items: { type: "string" }, + }, + template: { + type: "object", + properties: { + componentId: { type: "string" }, + dataBinding: { type: "string" }, + }, + required: ["componentId", "dataBinding"], + }, + }, + }, + distribution: { + type: "string", + enum: [ + "start", + "center", + "end", + "spaceBetween", + "spaceAround", + "spaceEvenly", + ], + }, + alignment: { + type: "string", + enum: ["start", "center", "end", "stretch"], + }, + }, + required: ["children"], + }, + Column: { + type: "object", + properties: { + children: { + type: "object", + description: + "Defines the children. Use 'explicitList' for a fixed set of children, or 'template' to generate children from a data list.", + properties: { + explicitList: { + type: "array", + items: { type: "string" }, + }, + template: { + type: "object", + properties: { + componentId: { type: "string" }, + dataBinding: { type: "string" }, + }, + required: ["componentId", "dataBinding"], + }, + }, + }, + distribution: { + type: "string", + enum: [ + "start", + "center", + "end", + "spaceBetween", + "spaceAround", + "spaceEvenly", + ], + }, + alignment: { + type: "string", + enum: ["start", "center", "end", "stretch"], + }, + }, + required: ["children"], + }, + List: { + type: "object", + properties: { + children: { + type: "object", + description: + "Defines the children. Use 'explicitList' for a fixed set of children, or 'template' to generate children from a data list.", + properties: { + explicitList: { + type: "array", + items: { type: "string" }, + }, + template: { + type: "object", + properties: { + componentId: { type: "string" }, + dataBinding: { type: "string" }, + }, + required: ["componentId", "dataBinding"], + }, + }, + }, + direction: { + type: "string", + enum: ["vertical", "horizontal"], + }, + alignment: { + type: "string", + enum: ["start", "center", "end", "stretch"], + }, + }, + required: ["children"], + }, + Card: { + type: "object", + properties: { child: { type: "string" } }, + required: ["child"], + }, + Tabs: { + type: "object", + properties: { + tabItems: { + type: "array", + items: { + type: "object", + properties: { + title: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + child: { type: "string" }, + }, + required: ["title", "child"], + }, + }, + }, + required: ["tabItems"], + }, + Divider: { + type: "object", + properties: { + axis: { + type: "string", + enum: ["horizontal", "vertical"], + }, + }, + }, + Modal: { + type: "object", + properties: { + entryPointChild: { type: "string" }, + contentChild: { type: "string" }, + }, + required: ["entryPointChild", "contentChild"], + }, + Button: { + type: "object", + properties: { + label: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + action: { + type: "object", + properties: { + name: { type: "string" }, + context: { + type: "array", + items: { + type: "object", + properties: { + key: { type: "string" }, + value: { + type: "object", + properties: { + path: { type: "string" }, + literal: { type: "string" }, + literalNumber: { type: "number" }, + literalBoolean: { type: "boolean" }, + }, + }, + }, + required: ["key", "value"], + }, + }, + }, + required: ["name"], + }, + }, + required: ["label", "action"], + }, + CheckBox: { + type: "object", + properties: { + label: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + value: { + type: "object", + properties: { + literalBoolean: { type: "boolean" }, + path: { type: "string" }, + }, + }, + }, + required: ["label", "value"], + }, + TextField: { + type: "object", + properties: { + label: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + text: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + textFieldType: { + type: "string", + enum: ["shortText", "number", "date", "longText"], + }, + validationRegexp: { type: "string" }, + }, + required: ["label"], + }, + DateTimeInput: { + type: "object", + properties: { + value: { + type: "object", + properties: { + literalString: { type: "string" }, + path: { type: "string" }, + }, + }, + enableDate: { type: "boolean" }, + enableTime: { type: "boolean" }, + outputFormat: { type: "string" }, + }, + required: ["value"], + }, + MultipleChoice: { + type: "object", + properties: { + selections: { + type: "object", + properties: { + literalArray: { + type: "array", + items: { type: "string" }, + }, + path: { type: "string" }, + }, + }, + options: { + type: "array", + items: { + type: "object", + properties: { + label: { + type: "object", + properties: { + literal: { type: "string" }, + path: { type: "string" }, + }, + }, + value: { type: "string" }, + }, + required: ["label", "value"], + }, + }, + maxAllowedSelections: { type: "integer" }, + }, + required: ["selections", "options"], + }, + Slider: { + type: "object", + properties: { + value: { + type: "object", + properties: { + literalNumber: { type: "number" }, + path: { type: "string" }, + }, + }, + minValue: { type: "number" }, + maxValue: { type: "number" }, + }, + required: ["value"], + }, + }, + }, + }, + required: ["id", "component"], + }, + }, + }, + required: ["components"], + }, + dataModelUpdate: { + type: "object", + description: "Updates the data model for a surface.", + properties: { + path: { + type: "string", + description: + "An optional path to a location within the data model (e.g., 'user.name'). If omitted, the entire data model will be replaced.", + }, + contents: { + type: "array", + description: "A list of key-value pairs representing the data.", + items: { + type: "object", + description: + "A single data entry. Exactly one 'value_' property should be provided alongside the key.", + properties: { + key: { + type: "string", + description: "The key for this data entry.", + }, + value_string: { + type: "string", + description: "A string value.", + }, + value_number: { + type: "number", + description: "A number value.", + }, + value_boolean: { + type: "boolean", + description: "A boolean value.", + }, + }, + required: ["key"], + }, + }, + }, + required: ["contents"], + }, + surfaceDeletion: { + type: "object", + description: + "Signals the client to delete the surface. The object should be empty; its presence is the signal. Only include if the surface is to be deleted.", + properties: { unused: { type: "string" } }, + }, + }, + required: ["surfaceId"], +}; + +const uiSchemaLite = { + ...uiSchema.properties.surfaceUpdate.properties.components.items, +}; diff --git a/experiments/agent/src/define-function.ts b/experiments/agent/src/define-function.ts new file mode 100644 index 00000000000..c8d75c53bb7 --- /dev/null +++ b/experiments/agent/src/define-function.ts @@ -0,0 +1,83 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { FunctionDeclaration } from "@google/genai"; +import { z, ZodObject, ZodTypeAny } from "zod"; +import zodToJsonSchema from "zod-to-json-schema"; + +export type ZodFunctionDefinition< + TParams extends ArgsRawShape, + TResponse extends ArgsRawShape, +> = { + name: string; + description: string; + parameters: TParams; + response?: TResponse; +}; + +type ArgsRawShape = { + [k: string]: ZodTypeAny; +}; + +export type Handler< + TParams extends ArgsRawShape, + TResponse extends ArgsRawShape, +> = ( + args: z.infer> +) => Promise>>; + +type TypedFunctionDefinition< + TParams extends ArgsRawShape, + TResponse extends ArgsRawShape, +> = FunctionDeclaration & { + handler: Handler; +}; + +export type FunctionDefinition = TypedFunctionDefinition; + +export { defineFunction, defineFunctionLoose }; + +function defineFunction< + TParams extends ArgsRawShape, + TResponse extends ArgsRawShape, +>( + definition: ZodFunctionDefinition, + handler: Handler +): TypedFunctionDefinition { + const { parameters, response, name, description } = definition; + // Convert Zod schemas to JSON Schema + const parametersJsonSchema = zodToJsonSchema(z.object(parameters)); + const result: TypedFunctionDefinition = { + name, + description, + parametersJsonSchema, + handler, + }; + if (response) { + result["responseJsonSchema"] = zodToJsonSchema(z.object(response)); + } + return result; +} + +function defineFunctionLoose( + definition: FunctionDeclaration, + handler: (args: Record) => Promise> +): FunctionDefinition { + const { parametersJsonSchema, responseJsonSchema, name, description } = + definition; + const result: FunctionDefinition = { + name, + description, + parametersJsonSchema, + handler, + }; + if (responseJsonSchema) { + result["responseJsonSchema"] = responseJsonSchema; + } + return result; +} diff --git a/experiments/agent/src/eval-set.ts b/experiments/agent/src/eval-set.ts new file mode 100644 index 00000000000..b72c7194446 --- /dev/null +++ b/experiments/agent/src/eval-set.ts @@ -0,0 +1,115 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export { evalSet }; + +const evalSet = new Map([ + /** + * Basic transfer from one agent to another. The hyperlinks + * serve as a way to declare various paths to transfer. + */ + [ + "routing", + `Ask the user (a middle schooler) about how they would +like to learn today. Offer them these choices and take them to the one they +choose: + +- Fun Learning Game +- Educational Cartoon +- Engaging Interactive Lesson +`, + ], + /** + * Basic "smarts with files" test: the agent has to figure out to feed + * provided images correctly into video gen in parallel, and then call the + * video concatenation tool to create a single video. + */ + [ + "mix-n-batch", + `Stitch these images into a video, with each image as a key +frame in the video: + + + + + + + +`, + ], + /** + * Tests that the agent is smart enough to save the text as file to pass + * it as outcome. + */ + ["text", `Generate a poem about opals`], + /** + * The classic "make me N insta posts" test. The agent must figure out how + * to generate ideas, then images from them, then save both and then + * interleave them. + */ + [ + "insta", + `Come up with five ideas for Halloween instagram posts and +generate images for all of them. Write each post text as a file. +Output as interleaved files: + +text + image + ... + +For context, this is for a small coffee shop in Mountain View.`, + ], + [ + /** + * Another "smarts with files" test. The agent must figure out that it needs + * to generate multiple keyframes, then call video gen to create a video. + */ + "monkey", + `Make a video of a monkey jumping. Use one prompt to generate +multiple keyframe images.`, + ], + [ + /** + * Use input test: the agent must ask the user for images with confirmation + * and handle rejection gracefully, then generate a video from the two + * images. + */ + "user-video", + `Create a video from two user-supplied images. When asking +for second image, show the first image as part of user prompt. +After images collected, show both images and ask to confirm that this is what +the user wants. If not, start over.`, + ], + [ + /** + * The classic "interview" test: The agent must collect the information + * about the business despite the user trying to derail the conversation, + * concluding with a confirmation. + */ + "interview", + `Collect the following information from the user: +- name of their business +- location of the business +- type of their business +The user may want to ask questions or want to have a conversation that is +not relevant to the information. Be polite and gently steer them toward +collecting the information. It may take more than one try. + +When you feel confident that you've collected the information, ask the user +to confirm`, + ], + [ + /** + * Simple chat: the agent must act as a conversation agent with memory. + */ + "chat", + `Have a conversation with the user, acting as the grizzled +pirate with a kind soul. Talk for as long as it takes, until the user +specifically signals that they're done with the conversation. + +After the user is done, save the summary of the conversation: just the key +points and things that might be useful to recall in the next chat with the +users`, + ], +]); diff --git a/experiments/agent/src/file-system.ts b/experiments/agent/src/file-system.ts new file mode 100644 index 00000000000..7b4f7299491 --- /dev/null +++ b/experiments/agent/src/file-system.ts @@ -0,0 +1,40 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { mkdir, writeFile } from "fs/promises"; +import mime from "mime"; +import { join } from "path"; + +export { getFileHandle, write }; + +let fileCount = 0; + +const KNOWN_TYPES = ["audio", "video", "image"]; + +const OUT_DIR = join(import.meta.dirname, "../out"); + +function getFileHandle(ext: string) { + return `/vfs/video${++fileCount}${ext}`; +} + +async function write(buffer: Buffer, mimeType: string) { + await mkdir(OUT_DIR, { recursive: true }); + const name = getFilename(mimeType); + await writeFile(join(OUT_DIR, name), buffer); + return `/vfs/${name}`; +} + +function getFilename(mimeType: string) { + const name = getName(mimeType); + const ext = mime.getExtension(mimeType); + return `${name}${++fileCount}.${ext}`; +} + +function getName(mimeType: string) { + const first = mimeType.split("/").at(0) || ""; + if (KNOWN_TYPES.includes(first)) return first; + return "file"; +} diff --git a/experiments/agent/src/functions/generate.ts b/experiments/agent/src/functions/generate.ts new file mode 100644 index 00000000000..c3ba3f13834 --- /dev/null +++ b/experiments/agent/src/functions/generate.ts @@ -0,0 +1,111 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from "zod"; +import { defineFunction } from "../define-function"; +import { getFileHandle, write } from "../file-system"; +import { GoogleGenAI } from "@google/genai"; + +export { generateFunctions }; + +const generateFunctions = [ + defineFunction( + { + name: "generate_video_from_frames", + description: + "Generates a video given two frames: starting frame and ending frame", + parameters: { + startFrame: z.string().describe( + `The starting frame of the video, specified as a VFS + path pointing to an existing image` + ), + endFrame: z.string() + .describe(`The end frame of the video, specified as a VFS path + pointing to an existing image`), + }, + response: { + video: z + .string() + .describe("The generated video, specified as a VFS path"), + }, + }, + async ({ startFrame, endFrame }) => { + console.log("Generating video from", startFrame, "to", endFrame); + return { video: getFileHandle(".mp4") }; + } + ), + defineFunction( + { + name: "generate_images_from_prompt", + description: `Generates one or more images based on a prompt`, + parameters: { + prompt: z.string() + .describe(`Detailed prompt to use for image generation. + +This model can generate multiple images from a single prompt. Especially when +looking for consistency across images (for instance, when generating video +keyframews), this is a very useful capability. + +Be specific about how many images to generate. + +When composing the prompt, be as descriptive as possible. Describe the scene, don't just list keywords. + +The model's core strength is its deep language understanding. A narrative, descriptive paragraph will almost always produce a better, more coherent image than a list of disconnected words. + +The following strategies will help you create effective prompts to generate exactly the images you're looking for. + +- Be Hyper-Specific: The more detail you provide, the more control you have. Instead of "fantasy armor," describe it: "ornate elven plate armor, etched with silver leaf patterns, with a high collar and pauldrons shaped like falcon wings." +- Provide Context and Intent: Explain the purpose of the image. The model's understanding of context will influence the final output. For example, "Create a logo for a high-end, minimalist skincare brand" will yield better results than just "Create a logo." + +- Use Step-by-Step Instructions: For complex scenes with many elements, break your prompt into steps. "First, create a background of a serene, misty forest at dawn. Then, in the foreground, add a moss-covered ancient stone altar. Finally, place a single, glowing sword on top of the altar." + +- Use "Semantic Negative Prompts": Instead of saying "no cars," describe the desired scene positively: "an empty, deserted street with no signs of traffic." + +- Control the Camera: Use photographic and cinematic language to control the composition. Terms like wide-angle shot, macro shot, low-angle perspective + +- Use the full breadth of styles: + +1. Photorealistic scenes - For realistic images, use photography terms. Mention camera angles, lens types, lighting, and fine details to guide the model toward a photorealistic result. + +2. Stylized illustrations & stickers - To create stickers, icons, or assets, be explicit about the style and request a transparent background. + +3. Accurate text in images - Gemini excels at rendering text. Be clear about the text, the font style (descriptively), and the overall design. + +4. Product mockups & commercial photography - Perfect for creating clean, professional product shots for e-commerce, advertising, or branding. + +5. Minimalist & negative space design - Excellent for creating backgrounds for websites, presentations, or marketing materials where text will be overlaid. + +6. Sequential art (Comic panel / Storyboard) - Builds on character consistency and scene description to create panels for visual storytelling. +`), + }, + response: { + images: z + .array( + z.string().describe(`A generated image, specified as a VFS path`) + ) + .describe(`Array of generated images`), + }, + }, + async ({ prompt }) => { + console.log("Generating image from prompt:", prompt); + const gemini = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY }); + const generated = await gemini.models.generateContent({ + model: "gemini-2.5-flash-image", + contents: prompt, + }); + const images = await Promise.all( + generated.candidates + ?.at(0) + ?.content?.parts?.filter((part) => "inlineData" in part) + .map(async (part) => { + const { data, mimeType } = part.inlineData!; + return write(Buffer.from(data!, "base64"), mimeType!); + }) || [] + ); + return { images }; + } + ), +]; diff --git a/experiments/agent/src/functions/system.ts b/experiments/agent/src/functions/system.ts new file mode 100644 index 00000000000..8c0f986803d --- /dev/null +++ b/experiments/agent/src/functions/system.ts @@ -0,0 +1,260 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import * as readline from "node:readline/promises"; +import { stdin as input, stdout as output } from "node:process"; +import * as path from "node:path"; +import { constants } from "node:fs"; +import { access } from "node:fs/promises"; + +import z from "zod"; +import { + defineFunction, + defineFunctionLoose, + FunctionDefinition, +} from "../define-function"; +import { getFileHandle, write } from "../file-system"; +import { examples, uiSchema } from "../a2ui"; + +export { systemFunctions, terminateLoop }; + +const FILES_DIR = path.join(import.meta.dirname, "../files"); + +let terminateLoop = false; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const simpleRequestUserInput: FunctionDefinition = defineFunction( + { + name: "system_request_user_input", + description: `Requests input from a user. Use this function to obtain +additional information or confirmation from the user. Use only when necessary. +Avoid excessive requests to the user.`, + parameters: { + user_message: z.string() + .describe(`Text to display to the user when requesting input. +Use the syntax to embed any files in the message`), + type: z.enum([ + "singleline-text", + "multiline-text", + "confirm", + "image", + "video", + ]).describe(`Type of the input requested. +- Use "singleline-text" to request a single line of text. Useful for chat-like +interactions, when only a brief text is requested. The requested text will be +delivered as "text" response. +- Use "multiline-text" to request multi-line text. Useful when requesting a +longer text, like a review, critique, further instructions, etc. The requested +text will be delivered as "text" response. +- Use "confirm" to request confirmation on an action. Use this only +when specifically requested by the objective. The confirmation will be +delivered as "yes" or "no" in "text" response. +- Use "image" to request an image. Once the user uploads the image, it will be +delivered as "file_path" response. +- Use "video" to request a video. Once the user uploads the video, it will be +delivered as "file_path" response. +`), + }, + response: { + text: z + .string() + .optional() + .describe( + `The text response from the user, populated when the "type" is "singleline-text", "multiline-text", or "confirm".` + ), + file_path: z.string().optional().describe(`The VFS path to the file, +uploaded by the user, populated when the "type" is "image", or "video".`), + }, + }, + async ({ user_message, type }) => { + const rl = readline.createInterface({ input, output }); + + try { + console.log(user_message); + + switch (type) { + case "singleline-text": + case "multiline-text": { + const answer = await rl.question("> "); + return { text: answer }; + } + + case "confirm": { + const answer = await rl.question("> (y/n) "); + const formattedAnswer = answer.trim().toLowerCase(); + return { + text: + formattedAnswer === "y" || formattedAnswer === "yes" + ? "yes" + : "no", + }; + } + + case "image": + case "video": { + const filename = await rl.question( + `> Please enter the filename for the ${type}: ` + ); + + const fullPath = path.join(FILES_DIR, filename); + const ext = path.extname(filename); + + try { + await access(fullPath, constants.R_OK); + console.log(`File found and accessible: ${fullPath}`); + // TODO: Implement actual file system. + return { file_path: getFileHandle(ext) }; + } catch { + console.error( + `Error: File not found or not accessible at "${fullPath}"` + ); + throw new Error(`File not found: ${filename}`); + } + } + + default: { + const exhaustiveCheck: never = type; + throw new Error(`Unsupported input type: "${exhaustiveCheck}"`); + } + } + } finally { + rl.close(); + } + } +); + +const a2uiRequestUserInput = defineFunctionLoose( + { + name: "system_request_user_input", + description: `Requests input from a user. Use this function to obtain +additional information or confirmation from the user. + +The input is requested by creating a layout for a User Interface. It will be using a format called A2UI which has a distinct schema, which I will provide to you, and which you must match. + +If the objective contains information about the UI to render, your job is to create the JSON payloads as a single array. Otherwise, use your best judgement. +In either case, ${examples}. + + +The Component Catalog you can use is defined in the surfaceUpdate components +list. + +The request must be a valid A2UI Protocol Message object necessary to satisfy the user request and build the UI from scratch. If you choose to return multiple +object, you must wrap them in an array, but you must provide the surfaces, +components and a beginRendering object so that it's clear what needs to be +rendered. + +Whenever you use a dataBinding you must start paths for child items with no +other prefixes such as 'item' etc. Keep the path purely related to the data +structure on which it is bound. + +IMPORTANT: You will be provided data so you MUST use that and never add, +remove, or alter it in any way. Every part in the provided MUST be +represented in the output, including text, media, headers, everything. + +ULTRA IMPORTANT: You MUST preserve all original paths for media. You must +also retain any line breaks in literal strings you generate. +`, + parametersJsonSchema: uiSchema, + }, + async (request) => { + console.log("REQUEST:\n", JSON.stringify(request, null, 2)); + throw new Error("NOT YET IMPLEMENTED"); + } +); + +const systemFunctions = [ + defineFunction( + { + name: "system_objective_fulfilled", + description: `Inidicates completion of the overall objective. +Call only when the specified objective is entirely fulfilled`, + parameters: { + user_message: z.string() + .describe(`Text to display to the user upon fulfillment of the objective. +Use the syntax to embed the outcome in the text`), + objective_outcomes: z + .array(z.string().describe(`A VFS path pointing at the outcome`)) + .describe( + `The array of outcomes that were requested in the objective` + ), + intermediate_files: z.array( + z.string().describe(`A VFS path pointing at the outcome`) + .describe(`Any intermediate files that were produced as a result +of fulfilling the objective `) + ), + href: z + .string() + .describe( + `The url of the next agent to which to transfer control upon +completion. By default, the control is transferred to the root agent "/". +If the objective specifies other agent URLs using the + title syntax, and calls to choose a different agent to which + to transfer control, then that url should be used instead.` + ) + .default("/"), + }, + }, + async ({ user_message, objective_outcomes, intermediate_files, href }) => { + console.log("SUCCESS! Objective fulfilled"); + console.log("User message:", user_message); + console.log("Transfer control to", href); + console.log("Objective outcomes:", objective_outcomes); + console.log("Intermediate files:", intermediate_files); + terminateLoop = true; + return {}; + } + ), + defineFunction( + { + name: "system_failed_to_fulfill_objective", + description: `Inidicates that the agent failed to fulfill of the overall +objective. Call ONLY when all means of fulfilling the objective have been +exhausted.`, + parameters: { + user_message: z.string() + .describe(`Text to display to the user upon admitting failure to +fulfill the objective. Provide a friendly explanation of why the objective +is impossible to fulfill and offer helpful suggestions`), + href: z + .string() + .describe( + `The url of the next agent to which to transfer control upon +failure. By default, the control is transferred to the root agent "/". +If the objective specifies other agent URLs using the + title syntax, and calls to choose a different agent to which + to transfer control, then that url should be used instead.` + ) + .default("/"), + }, + }, + async ({ user_message }) => { + console.log("FAILURE! Failed to fulfill the objective"); + console.log("User message:", user_message); + terminateLoop = true; + return {}; + } + ), + defineFunction( + { + name: "system_write_text_to_file", + description: "Writes provided text to a VFS file", + parameters: { + text: z.string().describe(`The text to write into a VFS file`), + }, + response: { + file_path: z + .string() + .describe("The VS path to the file containing the provided text"), + }, + }, + async ({ text }) => { + console.log("Writing text to file:", text); + const file_path = await write(Buffer.from(text), "text/markdown"); + return { file_path }; + } + ), + a2uiRequestUserInput, +]; diff --git a/experiments/agent/src/functions/video.ts b/experiments/agent/src/functions/video.ts new file mode 100644 index 00000000000..8709dc0edb6 --- /dev/null +++ b/experiments/agent/src/functions/video.ts @@ -0,0 +1,34 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import z from "zod"; +import { defineFunction } from "../define-function"; +import { getFileHandle } from "../file-system"; + +export { videoFunctions }; + +const videoFunctions = [ + defineFunction( + { + name: "concatenate_videos", + description: "Contatenates two or more videos together", + parameters: { + videos: z.array(z.string()) + .describe(`The array of the videos to concatenate. + The videos will be concatented in the order they are provided`), + }, + response: { + video: z + .string() + .describe("The resulting video, provided as a VFS path"), + }, + }, + async ({ videos }) => { + console.log("Concatenating videos", videos); + return { video: getFileHandle(".mp4") }; + } + ), +]; diff --git a/experiments/agent/src/index.ts b/experiments/agent/src/index.ts new file mode 100644 index 00000000000..1b8772420ab --- /dev/null +++ b/experiments/agent/src/index.ts @@ -0,0 +1,130 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { config } from "dotenv"; +import { + Content, + FunctionCallingConfigMode, + FunctionResponse, + GoogleGenAI, +} from "@google/genai"; +import { env } from "process"; +import { systemFunctions, terminateLoop } from "./functions/system"; +import { FunctionDefinition } from "./define-function"; +import { videoFunctions } from "./functions/video"; +import { generateFunctions } from "./functions/generate"; +import { evalSet } from "./eval-set"; +import { writeFile } from "fs/promises"; + +config(); + +const objective = evalSet.get("chat"); + +const systemInstruction = `You are an AI agent. Your job is to fulfill the +objective, specified at the start of the conversation context. + +You are linked with other AI agents via hyperlinks. The title +syntax points at another agent. If the objective calls for it, you can transfer +control to this agent. To transfer control, use the url of the agent in the +"href" parameter when calling "system_objective_fulfilled" or +"system_failed_to_fulfill_objective" function. As a result, the outcomes and the +intermediate files will be transferred to that agent. + +First, examine the problem in front of you and systematically break it down into +tasks. + +Can the objective be fulfilled? Do you have all the necessary tools? Is there +missing data? Can it be requested from the user. Answer this question +thoroughly and methodically. Do not make any assumptions. + +If there aren't tools available to fulfill the objective, admit failure, but +make sure to explain to the user why the objective is impossible to fulfill +and offer suggestions on what additionaltools might make the problem tractable. + +Otherwise, go on. + +Create a dependency tree for the tasks. Which tasks can be executed +concurrently and which ones must be executed serially? + +When faced with the choice of serial or concurrent execution, choose +concurrency to save precious time. + +Finally, formulate the precise plan for will reseult in +fulfilling the objective. Outline this plan on a scratchpad, so that it's clear +to you how to execute it. + +Now start to execute the plan. For concurrent tasks, make sure to generate +multiple funciton calls at the same time. + +After each task, examine: is the plan still good? Did the results of the tasks +affect the outcome? If not, keep going. Otherwise, reexamine the plan and +adjust it accordingly. +`; + +const functionDeclarations = [ + ...systemFunctions, + ...generateFunctions, + ...videoFunctions, +]; + +const functions = new Map( + functionDeclarations.map((item) => [item.name!, item]) +); + +const gemini = new GoogleGenAI({ apiKey: env.GEMINI_API_KEY }); +const contents: Content[] = [ + { + parts: [ + { + text: ` +${objective} +`, + }, + ], + }, +]; + +outerLoop: while (!terminateLoop) { + await writeFile("out.log", JSON.stringify(functionDeclarations)); + const generated = await gemini.models.generateContent({ + model: "gemini-flash-latest", + contents, + config: { + thinkingConfig: { includeThoughts: true, thinkingBudget: -1 }, + systemInstruction, + toolConfig: { + functionCallingConfig: { mode: FunctionCallingConfigMode.ANY }, + }, + tools: [{ functionDeclarations }], + }, + }); + // for await (const chunk of generated) { + const parts = generated.candidates?.at(0)?.content?.parts || []; + for (const part of parts) { + if (part.thought) { + console.log("THOUGHT", part.text); + } + } + const { functionCalls } = generated; + contents.push(generated.candidates!.at(0)!.content!); + if (functionCalls) { + for (const functionCall of functionCalls) { + const { name, args } = functionCall; + const fn = functions.get(name!); + if (!fn || !fn.handler) { + console.error(`Unknown function`, name); + break outerLoop; + } + const response = await fn.handler(args as Record); + const functionResponse: FunctionResponse = { + name, + response, + }; + contents.push({ parts: [{ functionResponse }] }); + } + } + // } +} diff --git a/experiments/logic/.gitignore b/experiments/logic/.gitignore new file mode 100644 index 00000000000..466e24805a9 --- /dev/null +++ b/experiments/logic/.gitignore @@ -0,0 +1 @@ +out/ \ No newline at end of file diff --git a/experiments/logic/README.md b/experiments/logic/README.md new file mode 100644 index 00000000000..505cfc476d2 --- /dev/null +++ b/experiments/logic/README.md @@ -0,0 +1,57 @@ +# The Logic Experiment + +Idea 1 (same as in screens experiment): what if LLM wrote a relatively small, +sandboxed piece that has access to capabilities, loosely following the +[object-capability model](https://en.wikipedia.org/wiki/Object-capability_model). +Could we then implement complex logic based on user's text description? + +Idea 2: What if simultaneously with writing code, LLM also wrote a test for this +code, and then tried to run these tests and fix the code based on the errors. + +The concept: give LLM a spec to implement an app as a function that is the +invoked inside of a sandbox. + +```js +export default async function (inputs, capabilities) { + const { mcp, generate, console } = capabilities; + + // generated code here +} +``` + +In this experiment, there are three capabilities: + +- `generate` -- provides access to LLM generation +- `mcp` -- the MCP client +- `console` -- the typical console stuff + +The code is generated as part of the build loop, which is shown below: + +```mermaid +graph TD + A[Start] --> B["Generate Code and Tests"]; + B --> C["Run Tests"]; + C --> D{Tests Pass?}; + D -- No --> E(Fix Loop); + subgraph E + direction TB + F["Fix Code"] --> G["Run Tests"]; + G --> H{Tests Pass?}; + H -- No --> F; + end + + D -- Yes --> I[Done ✅]; + H -- Yes --> I; +``` + +## Experimenting + +Create `.env` file with `GEMINI_API_KEY`. + +Run + +```sh +npm run build +``` + +Wait for the build iterations to finish and check results in `./out` directory. diff --git a/experiments/logic/package.json b/experiments/logic/package.json new file mode 100644 index 00000000000..3ebb36f29be --- /dev/null +++ b/experiments/logic/package.json @@ -0,0 +1,56 @@ +{ + "name": "logic", + "private": true, + "version": "1.0.0", + "main": "index.js", + "type": "module", + "scripts": { + "generate": "wireit", + "test": "wireit", + "fix": "wireit", + "build": "wireit" + }, + "wireit": { + "ts": { + "files": [ + "src/**/*.ts" + ] + }, + "fix": { + "command": "tsx src/fix-all.ts", + "dependencies": [ + "ts" + ] + }, + "build": { + "command": "tsx --experimental-vm-modules --no-warnings src/build-all.ts", + "dependencies": [ + "ts" + ] + }, + "generate": { + "command": "tsx src/generate-all.ts", + "dependencies": [ + "ts" + ] + }, + "test": { + "command": "tsx --experimental-vm-modules --no-warnings src/test-all.ts", + "dependencies": [ + "ts" + ] + } + }, + "keywords": [], + "author": "", + "license": "Apache-2.0", + "description": "", + "devDependencies": { + "tsx": "^4.20.6", + "wireit": "^0.15.0-pre.2" + }, + "dependencies": { + "@google/genai": "^1.27.0", + "dotenv": "^17.2.3" + } +} diff --git a/experiments/logic/src/build-all.ts b/experiments/logic/src/build-all.ts new file mode 100644 index 00000000000..904310d924f --- /dev/null +++ b/experiments/logic/src/build-all.ts @@ -0,0 +1,26 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { GoogleGenAI } from "@google/genai"; +import { config } from "dotenv"; +import { cases } from "./cases"; +import { build } from "./build"; + +config({ quiet: true }); + +const { GEMINI_API_KEY } = process.env; +if (!GEMINI_API_KEY) { + console.error( + ` 🔑 Please set GEMINI_KEY environment variable to run this app` + ); + process.exit(1); +} else { + console.log(` 🔑 GEMINI_KEY Acquired`); +} + +const gemini = new GoogleGenAI({ apiKey: GEMINI_API_KEY }); + +await Promise.all(cases.map((c) => build(gemini, c))); diff --git a/experiments/logic/src/build.ts b/experiments/logic/src/build.ts new file mode 100644 index 00000000000..d2c2d3e6659 --- /dev/null +++ b/experiments/logic/src/build.ts @@ -0,0 +1,54 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { GoogleGenAI } from "@google/genai"; +import { Case } from "./types"; +import { exists } from "./file-ops"; +import { fixCode } from "./fix-code"; +import { runTest } from "./run-test"; +import { generateCode } from "./generate-code"; + +export { build }; + +const MAX_ITERATIONS = 5; + +export type Status = { + done: boolean; +}; + +async function build(gemini: GoogleGenAI, c: Case) { + let count = MAX_ITERATIONS; + while (count--) { + const status = await runIteration(gemini, c); + if (status.done) return; + } +} + +async function runIteration(gemini: GoogleGenAI, c: Case): Promise { + const { name } = c; + if (await exists(c, "final")) { + console.log(`Done building "${name}"`); + return { done: true }; + } + + if (await exists(c, "errors")) { + console.log(`Fixing errors in "${name}"`); + await fixCode(gemini, c); + console.log(`Checking if fix worked in "${name}"`); + await runTest(c); + return { done: false }; + } + + if (await exists(c, "draft")) { + console.log(`Running tests for "${name}"`); + await runTest(c); + return { done: false }; + } + + console.log(`Generating code and test for "${name}"`); + await generateCode(gemini, c); + return { done: false }; +} diff --git a/experiments/logic/src/capabilities.ts b/experiments/logic/src/capabilities.ts new file mode 100644 index 00000000000..28a36eb398a --- /dev/null +++ b/experiments/logic/src/capabilities.ts @@ -0,0 +1,142 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + Content, + ContentUnion, + GoogleGenAI, + Tool, + ToolConfig, +} from "@google/genai"; +import { + Candidate, + GetUserEventsResponse, + UserEvent, + Capabilities, + GeminiInputs, + CallToolRequest, + SchemaValidated, +} from "./types"; + +class EventQueue { + resolve: ((response: GetUserEventsResponse) => void) | null = null; + queue: UserEvent[] = []; + + add(event: UserEvent) { + this.queue.push(event); + if (!this.resolve) return; + const events = [...this.queue]; + this.queue.length = 0; + const resolve = this.resolve; + this.resolve = null; + resolve({ + events, + isError: false, + }); + } + + async get(): Promise { + if (this.queue.length === 0) { + return new Promise((resolve) => { + this.resolve = resolve; + }); + } + const events = [...this.queue]; + this.queue.length = 0; + return { + events, + isError: false, + }; + } +} + +export class CapabilitiesImpl implements Capabilities { + readonly eventQueue = new EventQueue(); + #log: unknown[][] = []; + #vfs = new Map(); + + constructor(private readonly apiKey: string) {} + + #logToConsole(...params: unknown[]) { + this.#log = [...this.#log, params]; + } + + #processInlineData(candidates: Candidate[]): Candidate[] { + return candidates.map((candidate) => { + if (!candidate.content || !candidate.content.parts) { + return candidate; + } + + const parts = candidate.content.parts.map((part) => { + if (!("inlineData" in part)) { + return part; + } + + const { mimeType, data } = part.inlineData; + const byteCharacters = atob(data); + const byteNumbers = new Array(byteCharacters.length); + for (let i = 0; i < byteCharacters.length; i++) { + byteNumbers[i] = byteCharacters.charCodeAt(i); + } + const byteArray = new Uint8Array(byteNumbers); + const blob = new Blob([byteArray], { type: mimeType }); + const blobUrl = URL.createObjectURL(blob); + const vfsPath = `/vfs/out/${crypto.randomUUID()}`; + this.#vfs.set(vfsPath, blobUrl); + return { + fileData: { + fileUri: vfsPath, + mimeType, + }, + }; + }); + + return { ...candidate, content: { ...candidate.content, parts } }; + }); + } + + generate = { + generateContent: async (args: GeminiInputs) => { + this.#logToConsole("Calling generateContent:", args); + const gemini = new GoogleGenAI({ apiKey: this.apiKey }); + const result = await gemini.models.generateContent({ + model: args.model ?? "gemini-2.5-flash", + contents: args.contents as Content, + config: { + tools: args.tools as Tool[], + toolConfig: args.toolConfig as ToolConfig, + responseSchema: args.generationConfig?.responseSchema, + responseMimeType: args.generationConfig?.responseMimeType, + systemInstruction: args.systemInstruction as ContentUnion, + responseModalities: args.generationConfig?.responseModalities, + }, + }); + this.#logToConsole("generateContent returned:", result); + return { + candidates: this.#processInlineData(result.candidates as Candidate[]), + }; + }, + }; + mcp = { + callTool: async (params: CallToolRequest) => { + this.#logToConsole("Calling tool:", params); + throw new Error("Tool calling isn't yet implemented"); + }, + }; + console = { + log: (...params: unknown[]) => { + this.#logToConsole(...params); + }, + error: (...params: unknown[]) => { + this.#logToConsole("ERROR:", ...params); + }, + }; + prompts: Capabilities["prompts"] = { + get: (_id: string, _values?: Record) => { + throw new Error("Prompts aren't yet implemented"); + }, + }; +} diff --git a/experiments/logic/src/capability-mocks.ts b/experiments/logic/src/capability-mocks.ts new file mode 100644 index 00000000000..80f99c9191d --- /dev/null +++ b/experiments/logic/src/capability-mocks.ts @@ -0,0 +1,62 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + CallToolRequest, + CallToolResponse, + Capabilities, + CapabilityMocks, + Console, + GeminiInputs, + GeminiMock, + GeminiOutputs, + Prompt, + SchemaValidated, +} from "./types"; + +export class CapabilityMocksImpl implements CapabilityMocks { + constructor(private readonly reporter: Console) {} + + #callback?: (args: GeminiInputs) => Promise; + + readonly capabilities: Capabilities = { + generate: { + generateContent: async (args: GeminiInputs): Promise => { + if (!this.#callback) { + throw new Error("Callback not set"); + } + return this.#callback(args); + }, + }, + mcp: { + callTool: function (_params: CallToolRequest): Promise { + throw new Error("Function not implemented."); + }, + }, + console: { + error: (...params: unknown[]): void => { + this.reporter.error(...params); + }, + log: (...params: unknown[]): void => { + this.reporter.log(...params); + }, + }, + prompts: { + get: function ( + _id: string, + _values?: Record + ): Promise { + throw new Error("Function not implemented."); + }, + }, + }; + + readonly generate: GeminiMock = { + onGenerateContent: (callback) => { + this.#callback = callback; + }, + }; +} diff --git a/experiments/logic/src/cases.ts b/experiments/logic/src/cases.ts new file mode 100644 index 00000000000..bef41d219af --- /dev/null +++ b/experiments/logic/src/cases.ts @@ -0,0 +1,41 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Case } from "./types"; + +export const cases: Case[] = [ + { + name: "a-insta-caption", + prompt: `For each image in {{input1}}, provide a catchy caption suitable for an Instagram post. Output them collated into pairs: image + caption + image + caption, etc.`, + inputs: ["input1"], + }, + { + name: "b-count-images", + prompt: `Count the images in the {{input1}} and return the number of images as the only output`, + inputs: ["input1"], + }, + { + name: "interleave-images", + prompt: `Take images from {{input1}} and interleave them with images from {{input2}}. Disacard any other kinds of content.`, + inputs: ["input1", "input2"], + }, + { + name: "create-videos-from-frames", + prompt: `Make a series of generated videos based on the provided sequence of images: + +{{input1}} + +First, prepare the the list of tasks for the video model, starting with first image. Each task consists of the starting frame (current image in sequence) and end frame (next image in sequence). Then, generate video from each task. +`, + inputs: ["input1"], + }, + { + name: "insta-from-ideas", + prompt: `Take text that contain ideas in {{input1}}, then use Gemini to split it into JSON list of ideas. Then for each idea in the list, create a detailed prompt for an Instagram image and a caption that goes along with the image. Then, generate an image for each prompt. Output in pairs: image + caption + image + caption, etc. +`, + inputs: ["input1"], + }, +]; diff --git a/experiments/logic/src/common.ts b/experiments/logic/src/common.ts new file mode 100644 index 00000000000..46b51afdb3e --- /dev/null +++ b/experiments/logic/src/common.ts @@ -0,0 +1,77 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { readFile } from "fs/promises"; +import { join } from "path"; + +export { objectShapePrompt, jsDevPrompt, geminiModelPrompt, cleanupCode }; + +const SRC_DIR = join(import.meta.dirname, "../src"); + +function makeInputsType(items: string[]) { + return ` +type Inputs = { +${items.map((item) => ` ${item}: LLMContent;`)} +}`; +} + +function objectShapePrompt(inputs: string[]) { + return `The shape of the input object is as follows: +\`\`\`typescript +${makeInputsType(inputs)} +\`\`\``; +} + +function geminiModelPrompt() { + return `The following Gemini models are available: + +- \`gemini-2.5-pro\` - Enhanced thinking and reasoning, multimodal understanding, advanced coding, and more +- \`gemini-2.5-flash\` - Adaptive thinking, cost efficiency +- \`gemini-2.5-flash-image-preview\` - Precise, conversational image generation + and editing. Importantly, the JSON mode is not enabled for this model. +- \`veo-3.0-generate-001\` -- state-of-the-art model for generating high-fidelity videos from a text or image prompt. When two images submitted, will use the first image as the starting frame and the second image as the end frame. +`; +} + +async function jsDevPrompt(type: string) { + const typesPath = join(SRC_DIR, `types.ts`); + const types = await readFile(typesPath, "utf-8"); + + return `You will write a Javascript module with a single anonymous async function as a default export. + +The module runs in an isolated environment that has the latest ECMAScript features, but no additional bindings. The function you will write is defined as the \`${type}\` type. + +Make sure to write Javascript, not Typescript. Output it directly as Javascript code, with nothing else. This code will be used directly for execution. + +Here are all the type defintions: + +\`\`\`typescript +${types} +\`\`\``; +} + +function cleanupCode(s: string) { + // Mechanically fix a common problem with Gemini adding extra spaces in + // optional property accessors and ??. + s = s.replaceAll(/\?\s*\./g, "?.").replaceAll(/\?\s*\?/g, "??"); + + const content = s?.trim(); + if (!content) { + return "// No file generated"; + } + const lines = content.split("\n"); + const firstLine = lines[0]?.trim(); + const lastLine = lines.at(-1)?.trim(); + + const hasOpeningFence = firstLine?.startsWith("```"); + const hasClosingFence = lines.length > 1 && lastLine === "```"; + + if (hasOpeningFence && hasClosingFence) { + return lines.slice(1, -1).join("\n"); + } + + return s; +} diff --git a/experiments/logic/src/file-ops.ts b/experiments/logic/src/file-ops.ts new file mode 100644 index 00000000000..2982ef2cce6 --- /dev/null +++ b/experiments/logic/src/file-ops.ts @@ -0,0 +1,77 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { join } from "path"; +import { Case } from "./types"; +import { + access, + constants, + copyFile, + mkdir, + readFile, + rename, + rm, + writeFile, +} from "fs/promises"; + +export { write, read, copy, exists, remove, move }; + +const OUT_DIR = join(import.meta.dirname, "../out"); + +type FileType = "draft" | "test" | "errors" | "final"; + +async function write(c: Case, type: FileType, contents: string) { + const filename = join(OUT_DIR, `${c.name}${getSuffix(type)}`); + await mkdir(OUT_DIR, { recursive: true }); + return writeFile(filename, contents, "utf-8"); +} + +async function read(c: Case, type: FileType) { + const filename = join(OUT_DIR, `${c.name}${getSuffix(type)}`); + return readFile(filename, "utf-8"); +} + +async function copy(c: Case, from: FileType, to: FileType) { + const fromFile = join(OUT_DIR, `${c.name}${getSuffix(from)}`); + const toFile = join(OUT_DIR, `${c.name}${getSuffix(to)}`); + return copyFile(fromFile, toFile); +} + +async function move(c: Case, from: FileType, to: FileType) { + const fromFile = join(OUT_DIR, `${c.name}${getSuffix(from)}`); + const toFile = join(OUT_DIR, `${c.name}${getSuffix(to)}`); + return rename(fromFile, toFile); +} + +async function exists(c: Case, type: FileType) { + try { + const filename = join(OUT_DIR, `${c.name}${getSuffix(type)}`); + await access(filename, constants.F_OK); + return true; + } catch { + return false; + } +} + +async function remove(c: Case, type: FileType) { + const filename = join(OUT_DIR, `${c.name}${getSuffix(type)}`); + try { + return await rm(filename); + } catch { + return; + } +} + +function getSuffix(type: FileType) { + switch (type) { + case "errors": + return ".error.log"; + case "final": + return ".js"; + default: + return `.${type}.js`; + } +} diff --git a/experiments/logic/src/fix-all.ts b/experiments/logic/src/fix-all.ts new file mode 100644 index 00000000000..07f27b13060 --- /dev/null +++ b/experiments/logic/src/fix-all.ts @@ -0,0 +1,25 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { GoogleGenAI } from "@google/genai"; +import { config } from "dotenv"; +import { cases } from "./cases"; +import { fixCode } from "./fix-code"; + +config({ quiet: true }); + +const { GEMINI_API_KEY } = process.env; +if (!GEMINI_API_KEY) { + console.error( + ` 🔑 Please set GEMINI_KEY environment variable to run this app` + ); + process.exit(1); +} else { + console.log(` 🔑 GEMINI_KEY Acquired`); +} + +const gemini = new GoogleGenAI({ apiKey: GEMINI_API_KEY }); + +await Promise.all(cases.map(async (c) => await fixCode(gemini, c))); diff --git a/experiments/logic/src/fix-code.ts b/experiments/logic/src/fix-code.ts new file mode 100644 index 00000000000..b166c085ece --- /dev/null +++ b/experiments/logic/src/fix-code.ts @@ -0,0 +1,36 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import type { GoogleGenAI } from "@google/genai"; +import { Case } from "./types"; +import { loadFixer } from "./prompts/fixer"; +import { exists, read, write } from "./file-ops"; +import { cleanupCode } from "./common"; + +export { fixCode }; + +async function fixCode(gemini: GoogleGenAI, c: Case) { + console.log(` 🔨 Fixing code for "${c.name}"`); + + const hasDraft = await exists(c, "draft"); + if (!hasDraft) { + // Assume that we fixed all the bugs already + console.log(`No draft for ${c.name}`); + return; + } + const draft = await read(c, "draft"); + const test = await read(c, "test"); + const errors = await read(c, "errors"); + + const result = await gemini.models.generateContent( + await loadFixer(c, draft, test, errors) + ); + + const newDraftCode = cleanupCode(result.text!); + + await write(c, "draft", newDraftCode); + + console.log(` 🔨 Finished fixing code for "${c.name}"`); +} diff --git a/experiments/logic/src/generate-all.ts b/experiments/logic/src/generate-all.ts new file mode 100644 index 00000000000..c638e23b945 --- /dev/null +++ b/experiments/logic/src/generate-all.ts @@ -0,0 +1,25 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +import { GoogleGenAI } from "@google/genai"; +import { config } from "dotenv"; +import { cases } from "./cases"; +import { generateCode } from "./generate-code"; + +config({ quiet: true }); + +const { GEMINI_API_KEY } = process.env; +if (!GEMINI_API_KEY) { + console.error( + ` 🔑 Please set GEMINI_KEY environment variable to run this app` + ); + process.exit(1); +} else { + console.log(` 🔑 GEMINI_KEY Acquired`); +} + +const gemini = new GoogleGenAI({ apiKey: GEMINI_API_KEY }); + +await Promise.all(cases.map((c) => generateCode(gemini, c))); diff --git a/experiments/logic/src/generate-code.ts b/experiments/logic/src/generate-code.ts new file mode 100644 index 00000000000..040b3f5a01c --- /dev/null +++ b/experiments/logic/src/generate-code.ts @@ -0,0 +1,34 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { loadDeveloper } from "./prompts/developer"; +import { loadQA } from "./prompts/qa"; +import { Case } from "./types"; +import type { GoogleGenAI } from "@google/genai"; +import { write } from "./file-ops"; +import { cleanupCode } from "./common"; + +export { generateCode }; + +async function generateCode(gemini: GoogleGenAI, c: Case) { + console.log(` 🤖 Generating code for "${c.name}"`); + const [program, test] = await Promise.all([ + gemini.models.generateContent(await loadDeveloper(c)), + gemini.models.generateContent(await loadQA(c)), + ]); + + const draftCode = cleanupCode(program.text!); + const testCode = cleanupCode(test.text!); + + try { + await write(c, "draft", draftCode); + await write(c, "test", testCode); + } catch { + console.error(` ❌ failed to save to "${c.name}", exiting`); + process.exit(1); + } + console.log(` 🤖 Finished generating code for "${c.name}"`); +} diff --git a/experiments/logic/src/prompts/developer.ts b/experiments/logic/src/prompts/developer.ts new file mode 100644 index 00000000000..63464a74768 --- /dev/null +++ b/experiments/logic/src/prompts/developer.ts @@ -0,0 +1,39 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { GenerateContentParameters } from "@google/genai"; +import { geminiModelPrompt, jsDevPrompt, objectShapePrompt } from "../common"; +import { Case } from "../types"; + +export async function loadDeveloper( + definition: Case +): Promise { + const { prompt, inputs } = definition; + + return { + model: "gemini-2.5-pro", + contents: `Write the module that fulfills the following request: + +${prompt} + + +${objectShapePrompt(inputs)} +`, + config: { + systemInstruction: `You are a **Software Development Agent**. Your job is to examine the provided request to a software agent and fulfill in code. + +${await jsDevPrompt("Invoke")} + +Any files in this prompt will be provided to the program as "/vfs/in/file_[x]" +files, where x is the index of the file provided. + +When providing files as outputs, output them as \`FilePart\` structures within the +\`LLMContent\`, passing the VFS paths as-is. + +${geminiModelPrompt()}`, + }, + }; +} diff --git a/experiments/logic/src/prompts/fixer.ts b/experiments/logic/src/prompts/fixer.ts new file mode 100644 index 00000000000..f6543fa09f0 --- /dev/null +++ b/experiments/logic/src/prompts/fixer.ts @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { GenerateContentParameters } from "@google/genai"; +import { jsDevPrompt, objectShapePrompt } from "../common"; +import { Case } from "../types"; + +export async function loadFixer( + definition: Case, + draft: string, + test: string, + errors: string +): Promise { + const { prompt, inputs } = definition; + + return { + model: "gemini-2.5-pro", + contents: `Fix the errors with the module that fulfills the following request: + +${prompt} + + + +\`\`\`typescript +${draft} +\`\`\` + + + +\`\`\`typescript +${test} +\`\`\` + + + +${errors} + + + +${objectShapePrompt(inputs)}`, + config: { + systemInstruction: `You are a **Software Engineering Agent**. Your job is to complete identify and fix the problems in code. + + Step 1: Analyze the original code (surrounded with the "original-code" tags) that was written to fulfill the provided request (surrounded with the "request" tags), the test written for that code (surrounded with the "test-code" tags), and the errors (surrounded with the "errors" tag) that resulted when testing the original code for program. + + Step 2: Write a new revision of the original code. Your response must be the complete program. Do not shorten it or refer to original code. Your code will entirely replace it. + +${await jsDevPrompt("Invoke")} + +`, + }, + }; +} diff --git a/experiments/logic/src/prompts/qa.ts b/experiments/logic/src/prompts/qa.ts new file mode 100644 index 00000000000..8dfa96bea37 --- /dev/null +++ b/experiments/logic/src/prompts/qa.ts @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import type { GenerateContentParameters } from "@google/genai"; +import { jsDevPrompt, objectShapePrompt } from "../common"; +import { Case } from "../types"; + +export async function loadQA( + definition: Case +): Promise { + const { prompt, inputs } = definition; + + return { + model: "gemini-2.5-pro", + contents: `Write a test for the module that fulfills the following request: + +${prompt} + + +${objectShapePrompt(inputs)}`, + config: { + systemInstruction: `You are a **Software Test-Driven Development Agent**. Your job is to write a comprehensive test for program that will be written in order to fulfill the provided request. Your code will serve as the test spec for the future program. + +${await jsDevPrompt("Test")} + +When writing tests: +- be loose with text comparisons. The program may add extra line breaks for formatting. + + `, + }, + }; +} diff --git a/experiments/logic/src/run-in-vm.ts b/experiments/logic/src/run-in-vm.ts new file mode 100644 index 00000000000..304c29e1535 --- /dev/null +++ b/experiments/logic/src/run-in-vm.ts @@ -0,0 +1,32 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { createContext, Module, SourceTextModule } from "vm"; + +export async function prepareToRunInVM(code: string): Promise { + const context = createContext({}); + const module = new SourceTextModule(code, { context }); + const linker = async (specifier: string): Promise => { + throw new Error( + `Dynamic import not allowed: cannot resolve '${specifier}'` + ); + }; + + await module.link(linker); + await module.evaluate(); + + const defaultExport = (module.namespace as { default: object }).default; + + if (!defaultExport) { + throw new Error("The module must have a default export."); + } + if (typeof defaultExport !== "function") { + throw new Error( + `The default export must be a function, but received type '${typeof defaultExport}'.` + ); + } + return defaultExport as T; +} diff --git a/experiments/logic/src/run-test.ts b/experiments/logic/src/run-test.ts new file mode 100644 index 00000000000..fa15c0ea1a2 --- /dev/null +++ b/experiments/logic/src/run-test.ts @@ -0,0 +1,127 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { prepareToRunInVM } from "./run-in-vm"; +import { Case, Console, Invoke, Test, TestResultsReporter } from "./types"; +import { CapabilityMocksImpl } from "./capability-mocks"; +import { exists, move, read, remove, write } from "./file-ops"; + +export { runTest }; + +export type TestResult = { + readonly logs: ReadonlyArray>; + getLogAsString(): string; + readonly isError: boolean; +}; + +class TestFailedException extends Error {} + +class Reporter implements Console, TestResultsReporter, TestResult { + readonly logs: unknown[][] = []; + isError = false; + + constructor() { + this.progress = this.progress.bind(this); + this.fail = this.fail.bind(this); + this.success = this.success.bind(this); + + this.log = this.log.bind(this); + this.error = this.error.bind(this); + } + + progress(...params: unknown[]) { + this.logs.push(params); + } + + fail(...params: unknown[]) { + this.logs.push([`❌`, ...params]); + this.isError = true; + throw new TestFailedException(); + } + success(...params: unknown[]) { + this.logs.push([`✅`, ...params]); + } + log(...params: unknown[]): void { + this.logs.push([`🤖`, ...params]); + } + error(...params: unknown[]): void { + this.logs.push([`🤖`, ...params]); + } + + getLogAsString(): string { + const lines: string[] = []; + for (const item of this.logs) { + const objects: string[] = []; + for (const o of item) { + if (typeof o === "string") { + objects.push(o); + } else { + objects.push(JSON.stringify(o, null, 2)); + } + } + lines.push(objects.join(" ")); + } + return lines.join("\n"); + } +} + +async function runTest(c: Case): Promise { + const hasDraft = await exists(c, "draft"); + if (!hasDraft) { + return new Reporter(); + } + const result = await getTestResult(c); + if (result.isError) { + await write(c, "errors", result.getLogAsString()); + } else { + await remove(c, "errors"); + await move(c, "draft", "final"); + } + return result; +} + +async function getTestResult(c: Case): Promise { + const draftCode = await read(c, "draft"); + + const testCode = await read(c, "test"); + const reporter = new Reporter(); + + let test; + try { + test = await prepareToRunInVM(testCode); + } catch (e) { + reporter.error(`Test failed to compile`, e); + return reporter; + } + + let invoke; + try { + invoke = await prepareToRunInVM(draftCode); + } catch (e) { + reporter.error(`Program failed to compile`, e); + return reporter; + } + + const mocks = new CapabilityMocksImpl(reporter); + + try { + await test( + async (inputs) => { + return invoke(inputs, mocks.capabilities); + }, + mocks, + reporter + ); + reporter.log(`-- "${c.name}" Test Succeeded\n\n`); + return reporter; + } catch (e) { + reporter.error(`-- "${c.name}" Test failed\n\n`); + if (!(e instanceof TestFailedException)) { + reporter.error(e); + } + return reporter; + } +} diff --git a/experiments/logic/src/test-all.ts b/experiments/logic/src/test-all.ts new file mode 100644 index 00000000000..23013e598bb --- /dev/null +++ b/experiments/logic/src/test-all.ts @@ -0,0 +1,17 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { cases } from "./cases"; +import { runTest } from "./run-test"; + +await Promise.all( + cases.map(async (c) => { + const result = await runTest(c); + for (const item of result.logs) { + console.log(...item); + } + }) +); diff --git a/experiments/logic/src/types.ts b/experiments/logic/src/types.ts new file mode 100644 index 00000000000..0996a4bfc44 --- /dev/null +++ b/experiments/logic/src/types.ts @@ -0,0 +1,502 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * A use case to try + */ +export type Case = { + name: string; + prompt: string; + inputs: string[]; +}; + +export type Schema = { + type: "string" | "number" | "integer" | "boolean" | "object" | "array"; + format?: string; + description?: string; + nullable?: boolean; + enum?: string[]; + maxItems?: string | number; + minItems?: string | number; + properties?: Record; + anyOf?: Schema[]; + required?: string[]; + items?: Schema; +}; + +/** + * Represents data that was validated to conform to a JSON schema that is + * appropriate for the context. + */ +export type SchemaValidated = + | string + | number + | boolean + | null + | Array + | { + [K: string]: SchemaValidated; + }; + +export type CallToolRequest = { + name: string; + arguments: Record; +}; + +export type CallToolResponse = { + response?: SchemaValidated; + isError: boolean; +}; + +export type McpClient = { + callTool(params: CallToolRequest): Promise; +}; + +export type Console = { + /** + * Call this method to report errors. + * @param params -- useful information about the error, usually strings + */ + error(...params: unknown[]): void; + /** + * Call this method to log progress. + * @param params -- useful information to log, usually strings + */ + log(...params: unknown[]): void; +}; + +export type Capabilities = { + generate: Gemini; + mcp: McpClient; + console: Console; + /** + * The prompt capabilities. + */ + prompts: { + /** + * Gets a prompt by id. + * @param id The id of the prompt. + * @param values A property bag for substituting placeholders in the prompt. + * @returns The prompt with the placeholders substituted. + */ + get: ( + id: string, + values?: Record + ) => Promise; + }; +}; + +/** + * The entry point into the main program module. Must be a default export of the module. + */ +export type Invoke = ( + /** + * The inputs to the module. + */ + inputs: Record, + /** + * The capabilities, provided for the module. + */ + capabilities: Capabilities +) => Promise; + +export type Screen = { + screenId: string; + description: string; + inputSchema: Schema; + events: EventDescriptor[]; +}; + +export type EventDescriptor = { + eventId: string; + description: string; + /** + * The schema for the data that is dispatched along with the event. IF not + * present, there's no additional data supplied for this event. + */ + outputSchema?: Schema; +}; + +export type PromptArgument = { + /** + * The name of the argument. + */ + name: string; + /** + * Descriptiong of the argument: how will it be used in the prompt. + */ + description: string; + /** + * Whether or not the argument is required + */ + required: boolean; +}; + +export type Prompt = { + name: string; + description: string; + /** + * Whether prompt's generated output will be text, JSON, or image. + */ + format: "text" | "json" | "image"; + /** + * The arguments for the prompt that will populate prompt placeholders. + * For example, if the prompt has an {{origin}} placeholder in it, + * the expected value of arguments will be: + * + * ```json + * [ + * { + * "name": "origin", + * "description": "The origin point in the map", + * "required": true + * } + * ] + * ``` + */ + arguments?: PromptArgument[]; + /** + * The JSON schema that accompanies the prompt. Is only provided when + * the format = "json". Supply it as the `responseSchema` to the Gemini API. + */ + responseSchema?: Schema; + value: string; +}; + +export type ScreenInput = { + screenId: string; + inputs: SchemaValidated; +}; + +export type GetUserEventsResponse = { + events: UserEvent[]; + isError: boolean; +}; + +export type RenderScreenResponse = { + isError: boolean; +}; + +export type UserEvent = { + screenId: string; + eventId: string; + output?: SchemaValidated; +}; + +/** + * Access to Gemini API + */ +export type Gemini = { + generateContent(args: GeminiInputs): Promise; +}; + +export type HarmBlockThreshold = + // Content with NEGLIGIBLE will be allowed. + | "BLOCK_LOW_AND_ABOVE" + // Content with NEGLIGIBLE and LOW will be allowed. + | "BLOCK_MEDIUM_AND_ABOVE" + // Content with NEGLIGIBLE, LOW, and MEDIUM will be allowed. + | "BLOCK_ONLY_HIGH" + // All content will be allowed. + | "BLOCK_NONE" + // Turn off the safety filter. + | "OFF"; + +export type HarmCategory = + // Gemini - Harassment content + | "HARM_CATEGORY_HARASSMENT" + // Gemini - Hate speech and content. + | "HARM_CATEGORY_HATE_SPEECH" + // Gemini - Sexually explicit content. + | "HARM_CATEGORY_SEXUALLY_EXPLICIT" + // Gemini - Dangerous content. + | "HARM_CATEGORY_DANGEROUS_CONTENT" + // Gemini - Content that may be used to harm civic integrity. + | "HARM_CATEGORY_CIVIC_INTEGRITY"; + +export type Modality = "TEXT" | "IMAGE" | "AUDIO"; + +/** + * Allows choosing between various modes of the generated output. + * - To choose JSON mode (JSON output), set `responseMimeType` to + * `application/json` and provide `responseSchema`. + * - To choose text output mode, do not provide GenerationConfig at all + * - TO choese image output mode, set `responseModalities` to `["IMAGE"]` and + * do NOT set `responseMimeType`. + */ +export type GenerationConfig = { + responseMimeType?: "text/plain" | "application/json" | "text/x.enum"; + responseSchema?: Schema; + responseModalities?: Modality[]; +}; + +export type SafetySetting = { + category: HarmCategory; + threshold: HarmBlockThreshold; +}; + +export type FunctionCallPart = { + functionCall: { + name: string; + args: object; + }; +}; + +export type FunctionResponsePart = { + functionResponse: { + name: string; + response: object; + }; +}; + +export type TextPart = { + text: string; +}; + +export type DataStoreHandle = string; + +export type FileDataPart = { + fileData: { + /** + * Can be one of these three: + * - a URL pointing to a YT video + * - a URL pointing at a resource saved with File API. + * - a VFS path in the format of "/vfs/out/[guid]" + */ + fileUri: string; + mimeType: string; + resourceKey?: string; + }; +}; + +export type ExecutableCodePart = { + executableCode: { + language: "LANGUAGE_UNSPECIFIED" | "PYTHON"; + code: string; + }; +}; + +export type CodeExecutionResultOutcome = + // Unspecified status. This value should not be used. + | "OUTCOME_UNSPECIFIED" + // Code execution completed successfully. + | "OUTCOME_OK" + // Code execution finished but with a failure. stderr should contain the reason. + | "OUTCOME_FAILED" + // Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + | "OUTCOME_DEADLINE_EXCEEDED"; + +export type CodeExecutionResultPart = { + codeExecutionResult: { + outcome: CodeExecutionResultOutcome; + output: string; + }; +}; + +export type DataPart = + | InlineDataPart + | FileDataPart + | ExecutableCodePart + | CodeExecutionResultPart + | FunctionCallPart + | FunctionResponsePart + | TextPart; + +export type LLMContent = { + role?: string; + parts: DataPart[]; +}; + +/** + * Represents inline data, encoded as a base64 string. Use only for inputs. + * Outputs are always provided as FileData with VFS path. + */ +export type InlineDataPart = { + inlineData: { + mimeType: string; + data: string; + title?: string; + }; +}; + +export type GeminiInputs = { + model?: string; + contents: LLMContent[]; + tools?: Tool[]; + toolConfig?: ToolConfig; + systemInstruction?: LLMContent; + safetySettings?: SafetySetting[]; + generationConfig?: GenerationConfig; +}; + +export type Tool = { + functionDeclarations?: FunctionDeclaration[]; + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + googleSearch?: {}; + codeExecution?: CodeExecution; +}; + +export type ToolConfig = { + functionCallingConfig?: FunctionCallingConfig; +}; + +export type FunctionCallingConfig = { + mode?: "MODE_UNSPECIFIED" | "AUTO" | "ANY" | "NONE"; + allowedFunctionNames?: string[]; +}; + +export type FunctionDeclaration = { + name: string; + description: string; + parameters?: Schema; + response?: Schema; +}; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export type CodeExecution = { + // Type contains no fields. +}; + +export type FinishReason = + // Natural stop point of the model or provided stop sequence. + | "STOP" + // The maximum number of tokens as specified in the request was reached. + | "MAX_TOKENS" + // The response candidate content was flagged for safety reasons. + | "SAFETY" + // The response candidate content was flagged for image safety reasons. + | "IMAGE_SAFETY" + // The response candidate content was flagged for recitation reasons. + | "RECITATION" + // The response candidate content was flagged for using an unsupported language. + | "LANGUAGE" + // Unknown reason. + | "OTHER" + // Token generation stopped because the content contains forbidden terms. + | "BLOCKLIST" + // Token generation stopped for potentially containing prohibited content. + | "PROHIBITED_CONTENT" + // Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + | "SPII" + // The function call generated by the model is invalid. + | "MALFORMED_FUNCTION_CALL"; + +export type GroundingMetadata = { + groundingChunks: { + web: { + uri: string; + title: string; + }; + }[]; + groundingSupports: { + groundingChunkIndices: number[]; + confidenceScores: number[]; + segment: { + partIndex: number; + startIndex: number; + endIndex: number; + text: string; + }; + }; + webSearchQueries: string[]; + searchEntryPoint: { + renderedContent: string; + /** + * Base64 encoded JSON representing array of tuple. + * A base64-encoded string. + */ + sdkBlob: string; + }; + retrievalMetadata: { + googleSearchDynamicRetrievalScore: number; + }; +}; + +export type Candidate = { + /** + * The LLM output. + * IMPORTANT: Unlike the standard Gemini API, any media will be provided as + * the `FileDataPart` with the `fileUri` populated with the VFS file path. + * The VFS is the virtual file system that allows efficiently passing large + * media files within the application. The VFS paths are opaque identifiers + * for media files and can be provided as both inputs and outputs. The VFS + * files always start with "/vfs/". + * Note, that the `FileDataPart` might be mixed with `TextPart`s. When + * looking for it, first filter out the text parts and then get the first + * `FileDataPart`. + */ + content?: LLMContent; + finishReason?: FinishReason; + safetyRatings?: SafetySetting[]; + tokenOutput?: number; + groundingMetadata?: GroundingMetadata; +}; + +export type GeminiOutputs = { + candidates: Candidate[]; +}; + +export type AppImport = { + spec: string; + screens: Screen[]; + prompts: Prompt[]; +}; + +/** + * The entry point for the test program module. Must be a default export for + * the module. + */ +export type Test = ( + /** + * The program to test. + */ + invoke: Invoke, + /** + * The facilities to provide mock input and observe outputs. + */ + mocks: CapabilityMocks, + reporter: TestResultsReporter +) => Promise; + +export type TestResultsReporter = { + /** + * Use this function to provide additional info about the test: + * - progress + * - intermediate state + * - etc. + * @param params -- same parameters as console.info + */ + progress(...params: unknown[]): void; + /** + * Use this function to indicate that a test failed. Calling this function + * will terminate the test. + * @param params -- same parameters as console.error + */ + fail(...params: unknown[]): void; + /** + * Use this function to indicate that a test was a success. + * Can be called multiple times throughout the test, like for example, + * for each sub-test. + * @param params -- same parameters as console.log + */ + success(...params: unknown[]): void; +}; + +export type CapabilityMocks = { + generate: GeminiMock; +}; + +export type GeminiMock = { + /** + * Sets up a callback for the mocks. Call it before calling the Invoke + * function. + * + * @param callback called whenever the tested program calls `generateContent` + */ + onGenerateContent( + callback: (args: GeminiInputs) => Promise + ): void; +}; diff --git a/experiments/logic/tsconfig.json b/experiments/logic/tsconfig.json new file mode 100644 index 00000000000..558af8e6897 --- /dev/null +++ b/experiments/logic/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "node", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "allowJs": true, + "checkJs": false, + "resolveJsonModule": true, + "isolatedModules": true, + "lib": ["ESNext", "DOM"], + "experimentalDecorators": true, + "useDefineForClassFields": false + }, + "include": ["src/**/*.ts"] +} diff --git a/experiments/screens/.eslintrc.cjs b/experiments/screens/.eslintrc.cjs new file mode 100644 index 00000000000..485589e792a --- /dev/null +++ b/experiments/screens/.eslintrc.cjs @@ -0,0 +1,13 @@ +module.exports = { + // Your other configuration, such as extends, parser, etc. + // For example: + // extends: ['eslint:recommended'], + // parser: '@babel/eslint-parser', + + rules: { + // Other rules you have configured... + + // Disable the 'no-constant-condition' rule + "no-constant-condition": "off", + }, +}; diff --git a/experiments/screens/README.md b/experiments/screens/README.md new file mode 100644 index 00000000000..e273f80b760 --- /dev/null +++ b/experiments/screens/README.md @@ -0,0 +1,131 @@ +# The Screens Experiment + +The idea: what if LLM wrote a relatively small, sandboxed piece of code while +still being able to control UI and access capabilities, loosely following the +[object-capability model](https://en.wikipedia.org/wiki/Object-capability_model). + +The concept: give LLM a spec to implement an app as a function that is the +invoked inside of a sandbox. + +```js +export default async function (capabilities) { + const { mcp, generate, console } = capabilities; + + // generated code here +} +``` + +In this experiment, there are three capabilities: + +- `generate` -- provides access to LLM generation +- `mcp` -- the MCP client +- `console` -- the typical console stuff + +In this experiment, the MCP is not being used in a traditional way, where the +LLM calls it as it runs. Instead, LLM generates code that invokes MCP, which +allows for a couple of interesting possiblities: + +- we can now introspect the code and see what it does (also using LLM), so that + we can examine the logic. +- we can write tests for this code in parallel with writing the code. + +The MCP client offers access to the "Screen Server", which is the most +interesting one. It manages a set of predefined screens and allows the app +generated code to update them and receive user events. + +It has two methods: + +- `screens_get_user_events` -- gets the list of user events. Will block until it + receives at least one user event. Accumulates and drains the queue of user + events when called. + +- `screens_update_screens` - updates screens with specified ids. This call does + not block on user input. + +Combined together, `screens_get_user_events` and `screens_update_screens` form +the rendering loop for the application UI. + +It is up to the logic to link them together, followig the provided spec for the +app. + +## Experimenting + +To generate screens, edit the `src/screenify.ts` and change the `intent` and +`APP_NAME` to your liking. See sample values below. + +Then run + +```sh +npm run screenify +``` + +This will generate a set of screens and prompts in the `src/app/{APP_NAME}.ts` +file. + +To generate code from the screens: + +```sh +npm run generate {APP_NAME} +``` + +This will place the generated code in the `out/{APP_NAME}.js` file. + +To run code: + +- edit `runner.ts` to point to the right `out/{APP_NAME}.js` file. +- edit `capabilities.ts` to point to the right `src/app/{APP_NAME}.js` file. +- run + +```sh +npm run dev +``` + +## Example screenify prompts + +AI Slop or Not Game + +```ts +const intent = `Make an "AI slop or not" game, where the user picks from two +generated images based on the same topic, and the losing image is replaced +with a new image, for 10 rounds. After 10 rounds, the image that lasted the +longest is returned along with the "Winner" text.`; +const APP_NAME = "ai-slop-or-not"; +``` + +Blog Post Writer + +```ts +const intent = `Make a blog post writer. It takes a topic, then does some +research on it, then writes an outline, then generates an snazzy header +graphic based on this outline, and in parallel, writes the blog post based on +the outline. Then shows the header graphic and the blog post as a final +result.`; +const APP_NAME = "blog-post-writer"; +``` + +Adventure Game + +```ts +const spec = ` +Make a turn-based adventure game. + +First +- user enters inspiration for the game +- the initial plot line of the game is generated, inventing the character and the story and the objective (the boon, in hero's journey terms) of the story. +- the user is presented with bio and picture of their character. To create a picture, a detailed text prompt of the character suitable for an image generation is generated as well. +- the user can decide to accept the character or re-generate a new one +- once the user accepts, the game begins + +For each turn: +- present the user with a generated picture of the scene that follows the plot of the game, along with: + - brief text description of what is happening in the scene + - four choices for the user on what they could do next +- the user makes a choice +- based on the choice the user made, update the plot of the game ensuring that there's a path to the boon for the user. + +Once the user secures the boon, show a celebratory screen that includes a generated picture of the final scene and a text that describes that scene.`; +const APP_NAME = "adventure-game"; +``` + +You can see the generated code results in the `./out` directory. I checked them +in so you don't have to run all this mess. diff --git a/experiments/screens/index.html b/experiments/screens/index.html new file mode 100644 index 00000000000..ecd316802d8 --- /dev/null +++ b/experiments/screens/index.html @@ -0,0 +1,19 @@ + + + + + + Screens Demo + + + + + + + diff --git a/experiments/screens/obsolete/logic-prompt.md b/experiments/screens/obsolete/logic-prompt.md new file mode 100644 index 00000000000..1d10d83f44d --- /dev/null +++ b/experiments/screens/obsolete/logic-prompt.md @@ -0,0 +1,114 @@ +Process each picture by automatically cropping and enhancing it and return the +processed pictures. + +To accomplish this task, write a Javascript module with a single async function +as a default export. The module runs in an isolated environment that has the +latest ECMAScript features, but no additional bindings. The function you will +write is defined as `Invoke` type below: + +```ts +declare type JsonSerializable = + | string + | number + | boolean + | null + | Array + | { + [K: string]: JsonSerializable; + }; + +type CallToolRequest = { + name: string; + arguments: Record; +}; + +type TextContent = { + type: "text"; + text: string; +}; + +type ImageContent = { + type: "image"; + data: string; + mimeType: string; +}; + +type AudioContent = { + type: "audio"; + data: string; + mimeType: string; +}; + +type ResourceLinkContent = { + type: "resource_link"; + uri: string; + mimeType: string; +}; + +type ContentBlock = + | TextContent + | ImageContent + | AudioContent + | ResourceLinkContent; + +type CallToolResponse = { + content: ContentBlock[]; + isError: boolean; +}; + +type McpClient = { + callTool(params: CallToolRequest): Promise; +}; + +type Console = { + /** + * Call this method to report errors. + * @param params -- useful information about the error, usually strings + */ + error(...params: any[]): void; + /** + * Call this method to log progress. + * @param params -- useful information to log, usually strings + */ + log(...params: any[]): void; +}; + +type Capabilities = { + mcp: McpClient; + console: Console; +}; + +export type Invoke = (capabilities: Capabilities) => Promise; +``` + +The following tools are available via `mcp` capability: + +```json +[ + { + "name": "process_image", + "title": "Image Processor", + "description": "Automatically crops and enhances provided image. The output is a resource_link with with the uri pointing at the processed image", + "inputSchema": { + "type": "object", + "properties": { + "image_path": { + "type": "string", + "description": "VFS path to the image" + } + }, + "required": ["image_path"] + } + } +] +``` + +Any files in this prompt will be provided to the program as +"/vfs/in/file\_[x].[ext]" files, where x is the index of the file provided and +the ext is the extension of the file, based on its MIME type. + +When providing files as outputs, output them as `resource_link` structures in +the `ContentBlock`, converting paths to URIs like this: `file://${path}`. + +Make sure to write Javascript, not Typescript. Output it in markdown code +fences. diff --git a/experiments/screens/obsolete/sample-schema-1.json b/experiments/screens/obsolete/sample-schema-1.json new file mode 100644 index 00000000000..a9e77c01aad --- /dev/null +++ b/experiments/screens/obsolete/sample-schema-1.json @@ -0,0 +1,81 @@ +[ + { + "name": "process_image", + "title": "Image Processor", + "description": "Automatically crops and enhances provided image. The output is a `resource_link` with with the `uri` pointing at the processed image", + "inputSchema": { + "type": "object", + "properties": { + "image_uri": { + "type": "string", + "description": "VFS path to the image" + } + }, + "required": ["image_uri"] + } + }, + { + "name": "generate_image", + "title": "Generates an image based on the topic", + "description": "Generates an image based on the provided topic. This tool will expand the topic into a full prompt before generating. The output is a `resource_link` with with the `uri` pointing at the processed image", + "inputSchema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "The topic to base the image on" + } + }, + "required": ["topic"] + } + }, + { + "name": "review_with_user", + "title": "Review with User", + "description": "Asks user to review the picture. Returns ContentBlock `text` type containing `accepted` when the user accepts the picture or `rejected` when the user does not.", + "inputSchema": { + "type": "object", + "properties": { + "image_uri": { + "type": "string", + "description": "VFS uri of the image" + } + }, + "required": ["image_uri"] + } + }, + { + "name": "let_user_pick", + "title": "Let User Pick the Best Picture", + "description": "Asks user to review two pictures and choose one. Returns ContentBlock `resource_link` type with the `uri` pointing at the image the user picked.", + "inputSchema": { + "type": "object", + "properties": { + "image_a_uri": { + "type": "string", + "description": "VFS uri of image A" + }, + "image_b_uri": { + "type": "string", + "description": "VFS uri of image B" + } + }, + "required": ["image_a_uri", "image_b_uri"] + } + }, + { + "name": "convert_pdf_to_jpg", + "title": "Convert PDF to JPEG", + "description": "Converts PDF file to JPEG. Returns ContentBlock `resource_link` type with the `uri` pointing at the converted image", + "inputSchema": { + "type": "object", + "properties": { + "pdf_uri": { + "type": "string", + "description": "VFS path to the PDF file" + } + }, + "required": ["pdf_uri"] + } + } +] diff --git a/experiments/screens/obsolete/sample-schema-2.json b/experiments/screens/obsolete/sample-schema-2.json new file mode 100644 index 00000000000..ae6837c6407 --- /dev/null +++ b/experiments/screens/obsolete/sample-schema-2.json @@ -0,0 +1,50 @@ +[ + { + "name": "generate_image", + "title": "Generate Image from Prompt", + "description": "Generates a new image based on a detailed text prompt. Returns a `resource_link` content block with the `uri` pointing to the generated image.", + "inputSchema": { + "type": "object", + "properties": { + "prompt": { + "type": "string", + "description": "The text prompt describing the image to be generated." + } + }, + "required": ["prompt"] + } + }, + { + "name": "select_image_from_options", + "title": "Select Image from Options", + "description": "Presents a list of images to the user and prompts them to select one. Returns a `text` content block containing the `id` of the image selected by the user.", + "inputSchema": { + "type": "object", + "properties": { + "options": { + "type": "array", + "description": "An array of objects, each representing an image option for the user to choose from.", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "A unique identifier for this image option. This ID will be returned if the image is selected." + }, + "image_uri": { + "type": "string", + "description": "The VFS URI of the image to be displayed as an option. The `mimeType` of the image will be inferred." + } + }, + "required": ["id", "image_uri"] + } + }, + "question": { + "type": "string", + "description": "The question or prompt to display to the user along with the image options." + } + }, + "required": ["options", "question"] + } + } +] diff --git a/experiments/screens/obsolete/sample-schema-3.json b/experiments/screens/obsolete/sample-schema-3.json new file mode 100644 index 00000000000..e944781948d --- /dev/null +++ b/experiments/screens/obsolete/sample-schema-3.json @@ -0,0 +1,199 @@ +[ + { + "name": "generate_initial_game_setup", + "title": "Generate Initial Game Setup", + "description": "Creates the foundational elements of a new adventure game, including the protagonist's details, the overarching plot, and the primary objective (boon) based on user inspiration.", + "inputSchema": { + "type": "object", + "properties": { + "inspiration": { + "type": "string", + "description": "A brief text provided by the user to inspire the game's theme, setting, or core idea." + } + }, + "required": ["inspiration"] + }, + "outputSchema": { + "type": "object", + "properties": { + "character_name": { + "type": "string", + "description": "The name of the generated protagonist." + }, + "character_bio": { + "type": "string", + "description": "A detailed biography of the generated character." + }, + "character_image_prompt": { + "type": "string", + "description": "A detailed text prompt suitable for an image generation model, describing the character's appearance." + }, + "initial_plot_state": { + "type": "object", + "description": "The initial comprehensive state of the game's plot, including location, objective, character status, and items." + }, + "boon_description": { + "type": "string", + "description": "A description of the ultimate objective or 'boon' the character must achieve." + } + }, + "required": [ + "character_name", + "character_bio", + "character_image_prompt", + "initial_plot_state", + "boon_description" + ] + } + }, + { + "name": "generate_image_from_prompt", + "title": "Generate Image", + "description": "Creates a visual image based on a descriptive text prompt.", + "inputSchema": { + "type": "object", + "properties": { + "prompt": { + "type": "string", + "description": "A detailed text description for the image to be generated." + } + }, + "required": ["prompt"] + }, + "outputSchema": { + "type": "object", + "properties": { + "type": { "type": "string", "enum": ["resource_link"] }, + "uri": { + "type": "string", + "description": "VFS URI of the generated image." + }, + "mimeType": { + "type": "string", + "description": "MIME type of the image, e.g., 'image/jpeg' or 'image/png'." + } + }, + "required": ["type", "uri", "mimeType"] + } + }, + { + "name": "review_character_with_user", + "title": "Review Character", + "description": "Presents the generated character's biography and image to the user, allowing them to accept the character or request a regeneration.", + "inputSchema": { + "type": "object", + "properties": { + "character_bio": { + "type": "string", + "description": "The text biography of the generated character." + }, + "character_image_uri": { + "type": "string", + "description": "The VFS URI of the generated character's image." + } + }, + "required": ["character_bio", "character_image_uri"] + }, + "outputSchema": { + "type": "object", + "properties": { + "type": { "type": "string", "enum": ["text"] }, + "text": { + "type": "string", + "description": "User's decision: 'accepted' if the character is approved, or 'regenerate' if a new character is desired." + } + }, + "required": ["type", "text"] + } + }, + { + "name": "generate_next_turn_content", + "title": "Generate Next Turn Content", + "description": "Advances the game's plot, generating a new scene description, an image prompt for the scene, and four choices for the user, based on the current plot state and the user's previous action. It also returns the updated plot state and indicates if the boon was secured.", + "inputSchema": { + "type": "object", + "properties": { + "current_plot_state": { + "type": "object", + "description": "The current comprehensive state of the game's plot, including character status, location, inventory, and progress towards the objective." + }, + "previous_user_choice_index": { + "type": "number", + "description": "The index (0-3) of the choice the user made in the previous turn. Null if it's the first scene after character acceptance.", + "nullable": true + }, + "previous_scene_choices": { + "type": "array", + "items": { "type": "string" }, + "description": "The list of choices presented in the previous turn. Null if it's the first scene after character acceptance.", + "nullable": true + } + }, + "required": ["current_plot_state"] + }, + "outputSchema": { + "type": "object", + "properties": { + "scene_description": { + "type": "string", + "description": "A brief text description of what is happening in the current scene." + }, + "scene_image_prompt": { + "type": "string", + "description": "A detailed text prompt suitable for an image generation model, describing the current scene." + }, + "choices": { + "type": "array", + "items": { "type": "string" }, + "minItems": 4, + "maxItems": 4, + "description": "Four distinct choices the user can make, influencing the next turn." + }, + "new_plot_state": { + "type": "object", + "description": "The updated comprehensive state of the game's plot after this turn, reflecting changes due to the user's choice and narrative progression." + }, + "boon_secured_this_turn": { + "type": "boolean", + "description": "True if the game's ultimate objective (boon) was secured in this turn, otherwise false." + } + }, + "required": [ + "scene_description", + "scene_image_prompt", + "choices", + "new_plot_state", + "boon_secured_this_turn" + ] + } + }, + { + "name": "generate_final_scene_content", + "title": "Generate Final Scene Content", + "description": "Creates the celebratory text and image prompt for the final scene once the game's boon has been successfully secured.", + "inputSchema": { + "type": "object", + "properties": { + "final_plot_state": { + "type": "object", + "description": "The final comprehensive state of the game's plot, indicating the successful acquisition of the boon." + } + }, + "required": ["final_plot_state"] + }, + "outputSchema": { + "type": "object", + "properties": { + "final_scene_description": { + "type": "string", + "description": "A celebratory text description of the final scene, detailing the outcome of securing the boon." + }, + "final_scene_image_prompt": { + "type": "string", + "description": "A detailed text prompt suitable for an image generation model, describing the triumphant final scene." + } + }, + "required": ["final_scene_description", "final_scene_image_prompt"] + } + } +] diff --git a/experiments/screens/obsolete/sample-schema-4.json b/experiments/screens/obsolete/sample-schema-4.json new file mode 100644 index 00000000000..a9e77c01aad --- /dev/null +++ b/experiments/screens/obsolete/sample-schema-4.json @@ -0,0 +1,81 @@ +[ + { + "name": "process_image", + "title": "Image Processor", + "description": "Automatically crops and enhances provided image. The output is a `resource_link` with with the `uri` pointing at the processed image", + "inputSchema": { + "type": "object", + "properties": { + "image_uri": { + "type": "string", + "description": "VFS path to the image" + } + }, + "required": ["image_uri"] + } + }, + { + "name": "generate_image", + "title": "Generates an image based on the topic", + "description": "Generates an image based on the provided topic. This tool will expand the topic into a full prompt before generating. The output is a `resource_link` with with the `uri` pointing at the processed image", + "inputSchema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "The topic to base the image on" + } + }, + "required": ["topic"] + } + }, + { + "name": "review_with_user", + "title": "Review with User", + "description": "Asks user to review the picture. Returns ContentBlock `text` type containing `accepted` when the user accepts the picture or `rejected` when the user does not.", + "inputSchema": { + "type": "object", + "properties": { + "image_uri": { + "type": "string", + "description": "VFS uri of the image" + } + }, + "required": ["image_uri"] + } + }, + { + "name": "let_user_pick", + "title": "Let User Pick the Best Picture", + "description": "Asks user to review two pictures and choose one. Returns ContentBlock `resource_link` type with the `uri` pointing at the image the user picked.", + "inputSchema": { + "type": "object", + "properties": { + "image_a_uri": { + "type": "string", + "description": "VFS uri of image A" + }, + "image_b_uri": { + "type": "string", + "description": "VFS uri of image B" + } + }, + "required": ["image_a_uri", "image_b_uri"] + } + }, + { + "name": "convert_pdf_to_jpg", + "title": "Convert PDF to JPEG", + "description": "Converts PDF file to JPEG. Returns ContentBlock `resource_link` type with the `uri` pointing at the converted image", + "inputSchema": { + "type": "object", + "properties": { + "pdf_uri": { + "type": "string", + "description": "VFS path to the PDF file" + } + }, + "required": ["pdf_uri"] + } + } +] diff --git a/experiments/screens/obsolete/samples/adventure-game-generated-1.js b/experiments/screens/obsolete/samples/adventure-game-generated-1.js new file mode 100644 index 00000000000..a6c4b437961 --- /dev/null +++ b/experiments/screens/obsolete/samples/adventure-game-generated-1.js @@ -0,0 +1,431 @@ +export default async function Invoke(capabilities) { + const { generate, screens, console } = capabilities; + + const GEMINI_PRO = "gemini-2.5-pro"; + const GEMINI_IMAGE = "gemini-2.5-flash-image-preview"; + + const state = { + inspiration: "", + plot: "", + characterBio: "", + history: [], + lastChoices: [], + }; + + const resetState = () => { + state.inspiration = ""; + state.plot = ""; + state.characterBio = ""; + state.history = []; + state.lastChoices = []; + }; + + const generateAndParseJSON = async (model, prompt, history = []) => { + try { + const { candidates } = await generate.generateContent({ + model, + body: { + contents: [...history, prompt], + generationConfig: { + responseMimeType: "application/json", + }, + }, + }); + const jsonText = candidates[0].content.parts[0].text; + return JSON.parse(jsonText); + } catch (e) { + console.error("Failed to generate or parse JSON:", e); + await screens.updateScreens([ + { + screenId: "controls", + inputs: { + gameStatus: "An error occurred. Please try again.", + }, + }, + ]); + return null; + } + }; + + const generateImage = async (prompt) => { + try { + const { candidates } = await generate.generateContent({ + model: GEMINI_IMAGE, + body: { + contents: [ + { + parts: [ + { + text: prompt, + }, + ], + }, + ], + }, + }); + if (candidates && candidates[0].content.parts[0].fileData) { + return candidates[0].content.parts[0].fileData.fileUri; + } + } catch (e) { + console.error("Failed to generate image:", e); + } + return ""; // Return empty string on failure + }; + + const generatePlotAndCharacter = async () => { + await screens.updateScreens([ + { + screenId: "controls", + inputs: { + gameStatus: "Crafting your epic tale...", + }, + }, + ]); + + const prompt = { + role: "user", + parts: [ + { + text: `Generate a game story based on this inspiration: "${state.inspiration}". + +You are a creative and engaging storyteller for a text-based adventure game. Your task is to create a compelling initial story based on a user's inspiration. + +You must generate a JSON object with the following structure: +{ + "plot": "A paragraph describing the initial plotline, the world, the character's motivation, and the ultimate objective, which is called the 'boon'. The story should follow the hero's journey structure.", + "characterBio": "A short, engaging biography of the main character, including their name, background, and personality.", + "characterImagePrompt": "A detailed, cinematic, and visually rich text prompt suitable for an image generation model. Describe the character's appearance, clothing, gear, and the background setting. Focus on visual details. Use evocative adjectives. Style: fantasy concept art, hyperrealistic, dramatic lighting." +}`, + }, + ], + }; + + const data = await generateAndParseJSON(GEMINI_PRO, prompt); + if (!data) return; + + state.plot = data.plot; + state.characterBio = data.characterBio; + + const imagePath = await generateImage(data.characterImagePrompt); + if (!imagePath) { + await screens.updateScreens([ + { + screenId: "controls", + inputs: { + gameStatus: "Failed to create character image. Please try again.", + }, + }, + ]); + return; + } + + await screens.updateScreens([ + { + screenId: "choose_character", + inputs: { + bio: data.characterBio, + picture: imagePath, + }, + }, + ]); + await screens.updateScreens([ + { + screenId: "controls", + inputs: { + gameStatus: "A hero is born. Will you accept this destiny?", + }, + }, + ]); + }; + + const generateNextScene = async () => { + const systemInstruction = { + role: "system", + parts: [ + { + text: `You are a master storyteller continuing a turn-based adventure game. The initial premise is: ${state.plot}. The player character's bio is: ${state.characterBio}. Based on the story so far and the user's last choice, you will generate the next scene. The game must always have a clear path for the player to progress towards achieving the original boon. The story should be engaging and the choices should be meaningful. + +You must determine if the story has reached its conclusion. +- If the boon has been secured, the player has won. Generate a JSON object with this structure: \`{"isFinale": true, "finaleText": "A celebratory and descriptive paragraph concluding the story.", "finaleImagePrompt": "A detailed, cinematic prompt for the final celebratory image, capturing the moment of triumph."}\` +- Otherwise, continue the story. Generate a JSON object for the next turn with this structure: \`{"isFinale": false, "sceneText": "A brief but vivid text description of what is happening in the current scene.", "sceneImagePrompt": "A detailed, descriptive prompt for the scene's image, focusing on the environment, mood, and any key characters or objects. Style: fantasy concept art, cinematic.", "choices": ["Choice 1 text", "Choice 2 text", "Choice 3 text", "Choice 4 text"]}\`. The four choices must be distinct, actionable, and lead to different immediate outcomes.`, + }, + ], + }; + + const conversation = [systemInstruction, ...state.history]; + const data = await generateAndParseJSON( + GEMINI_PRO, + conversation[conversation.length - 1], + conversation.slice(0, -1) + ); + + if (!data) return; + + if (data.isFinale) { + const imagePath = await generateImage(data.finaleImagePrompt); + state.history.push({ + role: "model", + parts: [ + { + text: data.finaleText, + }, + ], + }); + await screens.updateScreens([ + { + screenId: "finale", + inputs: { + image: imagePath, + text: data.finaleText, + }, + }, + { + screenId: "controls", + inputs: { + gameStatus: "Your epic journey has reached its conclusion!", + }, + }, + ]); + } else { + const imagePath = await generateImage(data.sceneImagePrompt); + state.lastChoices = data.choices; + state.history.push({ + role: "model", + parts: [ + { + text: `Scene: ${data.sceneText}\nChoices: ${data.choices.join(", ")}`, + }, + ], + }); + await screens.updateScreens([ + { + screenId: "scene", + inputs: { + image: imagePath, + text: data.sceneText, + choice1: data.choices[0], + choice2: data.choices[1], + choice3: data.choices[2], + choice4: data.choices[3], + }, + }, + { + screenId: "controls", + inputs: { + gameStatus: "Your turn. What will you do?", + }, + }, + ]); + } + }; + + // --- Event Handlers --- + + const handleStartGameEvent = async (event) => { + if (event.eventId === "generate_inspiration") { + await screens.updateScreens([ + { + screenId: "controls", + inputs: { + gameStatus: "Generating inspiration...", + }, + }, + ]); + const { candidates } = await generate.generateContent({ + model: GEMINI_PRO, + body: { + contents: [ + { + parts: [ + { + text: "Generate a short, two-to-three word, evocative inspiration for a fantasy adventure game. For example: 'Sunken City of Robots' or 'The Whispering Mountain'.", + }, + ], + }, + ], + }, + }); + const generatedInspiration = candidates[0].content.parts[0].text.trim(); + await screens.updateScreens([ + { + screenId: "start_game", + inputs: { + generatedInspiration, + }, + }, + { + screenId: "controls", + inputs: { + gameStatus: "Ready to start a new adventure.", + }, + }, + ]); + } else if (event.eventId === "start") { + state.inspiration = event.data.inspiration; + await generatePlotAndCharacter(); + } + }; + + const handleChooseCharacterEvent = async (event) => { + if (event.eventId === "regenerate") { + await generatePlotAndCharacter(); + } else if (event.eventId === "choose") { + await screens.updateScreens([ + { + screenId: "controls", + inputs: { + gameStatus: "The adventure begins...", + }, + }, + ]); + state.history.push({ + role: "user", + parts: [ + { + text: "Let the adventure begin.", + }, + ], + }); + await generateNextScene(); + } + }; + + const handleSceneEvent = async (event) => { + if (event.eventId === "choose") { + const choiceIndex = event.data.choice - 1; + const chosenText = state.lastChoices[choiceIndex]; + state.history.push({ + role: "user", + parts: [ + { + text: `I choose to: ${chosenText}`, + }, + ], + }); + await screens.updateScreens([ + { + screenId: "controls", + inputs: { + gameStatus: "The story unfolds...", + }, + }, + ]); + await generateNextScene(); + } + }; + + const handleFinaleEvent = async (event) => { + if (event.eventId === "restart") { + resetState(); + await screens.updateScreens([ + { + screenId: "start_game", + inputs: {}, + }, + { + screenId: "controls", + inputs: { + gameStatus: "Ready to start a new adventure.", + }, + }, + ]); + } + }; + + const handleControlsEvent = async (event) => { + if (event.eventId === "recap_game") { + if (state.history.length === 0) { + await screens.updateScreens([ + { + screenId: "game_recap", + inputs: { + recap: "# Your adventure hasn't started yet!", + }, + }, + ]); + return; + } + + await screens.updateScreens([ + { + screenId: "controls", + inputs: { + gameStatus: "Recalling your journey...", + }, + }, + ]); + const { candidates } = await generate.generateContent({ + model: GEMINI_PRO, + body: { + contents: [ + ...state.history, + { + role: "user", + parts: [ + { + text: "Based on the provided game history, write a concise summary of my journey so far in markdown format.", + }, + ], + }, + ], + }, + }); + const recapText = candidates[0].content.parts[0].text; + await screens.updateScreens([ + { + screenId: "game_recap", + inputs: { + recap: recapText, + }, + }, + { + screenId: "controls", + inputs: { + gameStatus: "Your turn. What will you do?", + }, + }, + ]); + } + }; + + // --- Main Application Logic --- + + await screens.updateScreens([ + { + screenId: "start_game", + inputs: {}, + }, + { + screenId: "controls", + inputs: { + gameStatus: "Ready to start a new adventure.", + }, + }, + ]); + + // eslint-disable-next-line no-constant-condition + while (true) { + const { events } = await screens.getUserEvents(); + for (const event of events) { + switch (event.screenId) { + case "start_game": + await handleStartGameEvent(event); + break; + case "choose_character": + await handleChooseCharacterEvent(event); + break; + case "scene": + await handleSceneEvent(event); + break; + case "finale": + await handleFinaleEvent(event); + break; + case "controls": + await handleControlsEvent(event); + break; + default: + console.log(`Unknown event from screen: ${event.screenId}`); + } + } + } +} diff --git a/experiments/screens/obsolete/samples/adventure-game-generated-2.js b/experiments/screens/obsolete/samples/adventure-game-generated-2.js new file mode 100644 index 00000000000..437f19a7da5 --- /dev/null +++ b/experiments/screens/obsolete/samples/adventure-game-generated-2.js @@ -0,0 +1,351 @@ +export default async ({ generate, screens, console }) => { + const GEMINI_TEXT_MODEL = "gemini-2.5-pro"; + const GEMINI_IMAGE_MODEL = "gemini-2.5-flash-image-preview"; + + // Helper function to call Gemini for text generation + const callGeminiText = async (prompt, jsonSchema = null) => { + const args = { + model: GEMINI_TEXT_MODEL, + body: { + contents: [ + { + parts: [ + { + text: prompt, + }, + ], + }, + ], + generationConfig: {}, + }, + }; + if (jsonSchema) { + args.body.generationConfig.responseMimeType = "application/json"; + args.body.generationConfig.responseSchema = jsonSchema; + } + + const { candidates } = await generate.generateContent(args); + const part = candidates[0].content.parts[0]; + if (part.text) { + return jsonSchema ? JSON.parse(part.text) : part.text; + } + console.error("Gemini text generation failed to return text.", part); + return null; + }; + + // Helper function to generate an image + const generateImage = async (prompt) => { + const { candidates } = await generate.generateContent({ + model: GEMINI_IMAGE_MODEL, + body: { + contents: [ + { + parts: [ + { + text: prompt, + }, + ], + }, + ], + }, + }); + if ( + candidates && + candidates.length > 0 && + candidates[0].content && + candidates[0].content.parts.length > 0 + ) { + const filePart = candidates[0].content.parts[0].fileData; + if (filePart) { + return filePart.fileUri; + } + } + console.error("Image generation failed. Response:", candidates); + // Return a placeholder or handle the error appropriately + return ""; + }; + + // Helper to update the game status on the controls screen + const updateStatus = async (text) => { + await screens.updateScreens([ + { + screenId: "controls", + inputs: { + gameStatus: text, + }, + }, + ]); + }; + + // Main game loop allowing for restarts + // eslint-disable-next-line no-constant-condition + while (true) { + let gameState = { + inspiration: "", + character: { + bio: "", + imagePrompt: "", + }, + plotHistory: [], + boon: "", + lastChoice: "The adventure begins!", + }; + + // 1. START SCREEN + await screens.updateScreens([ + { + screenId: "start_game", + inputs: {}, + }, + ]); + await updateStatus("Ready for an adventure?"); + + let inspiration = null; + while (!inspiration) { + const { events } = await screens.getUserEvents(); + const event = events[0]; + + if (event.screenId === "start_game") { + if (event.eventId === "generate_inspiration") { + await updateStatus("Generating inspiration..."); + const inspirationPrompt = + "Generate a one-sentence inspiration for a fantasy adventure game. For example: 'A fallen star that holds the key to eternal winter.' or 'The last dragon's egg, hidden in a forgotten city.'"; + const generatedInspiration = await callGeminiText(inspirationPrompt); + await screens.updateScreens([ + { + screenId: "start_game", + inputs: { + generatedInspiration, + }, + }, + ]); + await updateStatus("Ready for an adventure?"); + } else if (event.eventId === "start") { + if (event.data.inspiration && `${event.data.inspiration}`.trim()) { + inspiration = event.data.inspiration; + } + } + } + } + gameState.inspiration = inspiration; + + // 2. PLOT & CHARACTER GENERATION + await updateStatus("Creating your story..."); + const plotSchema = { + type: "object", + properties: { + character_bio: { + type: "string", + description: "A short, intriguing backstory for the main character.", + }, + story_premise: { + type: "string", + description: + "A summary of the world, the conflict, and the call to adventure.", + }, + boon: { + type: "string", + description: "The ultimate goal or object the hero seeks.", + }, + initial_scene: { + type: "string", + description: + "A description of the very first scene where the game begins.", + }, + }, + required: ["character_bio", "story_premise", "boon", "initial_scene"], + }; + const plotPrompt = `Based on the inspiration "${gameState.inspiration}", create a compelling story for a turn-based adventure game. The story should follow the hero's journey structure. Your output must be a JSON object conforming to the provided schema.`; + const initialPlot = await callGeminiText(plotPrompt, plotSchema); + gameState.character.bio = initialPlot.character_bio; + gameState.boon = initialPlot.boon; + gameState.plotHistory.push( + initialPlot.story_premise, + initialPlot.initial_scene + ); + + // 3. CHARACTER SELECTION LOOP + let characterAccepted = false; + while (!characterAccepted) { + await updateStatus("Generating your character..."); + const imagePromptGenPrompt = `Based on the following character bio, create a highly detailed image generation prompt for a character portrait. The prompt should describe the character's appearance, clothing, expression, and the style of the image (e.g., "digital painting, fantasy, detailed, cinematic lighting, vibrant colors"). Character Bio: ${gameState.character.bio}`; + gameState.character.imagePrompt = + await callGeminiText(imagePromptGenPrompt); + const characterPictureVfsPath = await generateImage( + gameState.character.imagePrompt + ); + + await screens.updateScreens([ + { + screenId: "choose_character", + inputs: { + bio: gameState.character.bio, + picture: characterPictureVfsPath, + }, + }, + ]); + await updateStatus("Will you accept this hero?"); + + const { events } = await screens.getUserEvents(); + const event = events[0]; + + if (event.screenId === "choose_character") { + if (event.eventId === "choose") { + characterAccepted = true; + } else if (event.eventId === "regenerate") { + await updateStatus("Let's try someone new..."); + const regenBioPrompt = `The player rejected the last character. Based on the same story premise ("${initialPlot.story_premise}"), create a new, different character bio.`; + gameState.character.bio = await callGeminiText(regenBioPrompt); + } + } + } + + // 4. MAIN GAMEPLAY LOOP + let isFinale = false; + let currentChoices = []; + while (!isFinale) { + await updateStatus("Generating the next scene..."); + const sceneSchema = { + type: "object", + properties: { + scene_description: { + type: "string", + description: + "A brief paragraph describing the current situation, continuing from the last action.", + }, + image_prompt: { + type: "string", + description: + "A detailed prompt for an image generator to create the scene's illustration.", + }, + choices: { + type: "array", + items: { + type: "string", + }, + minItems: 4, + maxItems: 4, + description: + "Four distinct, short, action-oriented strings for the player's next move.", + }, + is_finale: { + type: "boolean", + description: + "Set to true only if the player has definitively achieved the boon, false otherwise.", + }, + }, + required: ["scene_description", "image_prompt", "choices", "is_finale"], + }; + const storySoFar = gameState.plotHistory.join("\n\n"); + const scenePrompt = `You are the Dungeon Master. Continue the story. + Story So Far: ${storySoFar} + Character: ${gameState.character.bio} + Goal (The Boon): ${gameState.boon} + Player's Last Action: "${gameState.lastChoice}" + + Generate the next scene. Ensure the story always provides a path to achieving the boon. Your output must be a JSON object conforming to the provided schema.`; + + const sceneData = await callGeminiText(scenePrompt, sceneSchema); + isFinale = sceneData.is_finale; + currentChoices = sceneData.choices; + + if (isFinale) { + // Break the loop to proceed to the finale screen generation + break; + } + + const sceneImageVfsPath = await generateImage(sceneData.image_prompt); + gameState.plotHistory.push(sceneData.scene_description); + + await screens.updateScreens([ + { + screenId: "scene", + inputs: { + image: sceneImageVfsPath, + text: sceneData.scene_description, + choice1: currentChoices[0], + choice2: currentChoices[1], + choice3: currentChoices[2], + choice4: currentChoices[3], + }, + }, + ]); + await updateStatus("What will you do next?"); + + let choiceMade = false; + while (!choiceMade) { + const { events } = await screens.getUserEvents(); + const event = events[0]; + + if (event.screenId === "scene" && event.eventId === "choose") { + const choiceIndex = event.data.choice - 1; + gameState.lastChoice = currentChoices[choiceIndex]; + choiceMade = true; + } else if ( + event.screenId === "controls" && + event.eventId === "recap_game" + ) { + const recapText = `Your quest to find the ${gameState.boon}.\n\n--- YOUR STORY ---\n\n${gameState.plotHistory.join("\n\n")}`; + await screens.updateScreens([ + { + screenId: "game_recap", + inputs: { + recap: recapText, + }, + }, + ]); + } + } + } + + // 5. FINALE + await updateStatus("Reaching the grand finale..."); + const finaleSchema = { + type: "object", + properties: { + finale_text: { + type: "string", + description: + "A celebratory paragraph describing the triumphant final scene.", + }, + image_prompt: { + type: "string", + description: + "A detailed prompt for an image generator to create an epic illustration of this final scene.", + }, + }, + required: ["finale_text", "image_prompt"], + }; + const storySoFar = gameState.plotHistory.join("\n\n"); + const finalePrompt = `The story has concluded. The player has achieved their goal. + Story: ${storySoFar} + Character: ${gameState.character.bio} + Goal (The Boon): ${gameState.boon} + Player's final, successful action was: "${gameState.lastChoice}" + + Write the celebratory conclusion. Your output must be a JSON object conforming to the provided schema.`; + + const finaleData = await callGeminiText(finalePrompt, finaleSchema); + const finaleImageVfsPath = await generateImage(finaleData.image_prompt); + + await screens.updateScreens([ + { + screenId: "finale", + inputs: { + image: finaleImageVfsPath, + text: finaleData.finale_text, + }, + }, + ]); + await updateStatus("Congratulations, you have won!"); + + let wantsToRestart = false; + while (!wantsToRestart) { + const { events } = await screens.getUserEvents(); + const event = events[0]; + if (event.screenId === "finale" && event.eventId === "restart") { + wantsToRestart = true; + } + } + } +}; diff --git a/experiments/screens/obsolete/screens-logic-prompt.md b/experiments/screens/obsolete/screens-logic-prompt.md new file mode 100644 index 00000000000..0c5c3c78ba0 --- /dev/null +++ b/experiments/screens/obsolete/screens-logic-prompt.md @@ -0,0 +1,398 @@ +To accomplish this task, write a Javascript module with a single anonymous async +function as a default export. The module runs in an isolated environment that +has the latest ECMAScript features, but no additional bindings. The function you +will write is defined as `Invoke` type below: + +```typescript +type Schema = { + type: "string" | "number" | "integer" | "boolean" | "object" | "array"; + format?: string; + description?: string; + nullable?: boolean; + enum?: string[]; + maxItems?: string; + minItems?: string; + properties?: Record; + anyOf?: Schema[]; + required?: string[]; + items?: Schema; +}; + +/** + * Represents data that was validated to conform to a JSON schema that is + * appropriate for the context. + */ +type SchemaValidated = + | string + | number + | boolean + | null + | Array + | { + [K: string]: SchemaValidated; + }; + +type CallToolRequest = { + name: string; + arguments: Record; +}; + +type CallToolResponse = { + content: LLMContent; + isError: boolean; +}; + +type McpClient = { + callTool(params: CallToolRequest): Promise; +}; + +type Console = { + /** + * Call this method to report errors. + * @param params -- useful information about the error, usually strings + */ + error(...params: unknown[]): void; + /** + * Call this method to log progress. + * @param params -- useful information to log, usually strings + */ + log(...params: unknown[]): void; +}; + +type Capabilities = { + generate: Gemini; + mcp: McpClient; + console: Console; + screens: ScreenServer; +}; + +export type Invoke = (capabilities: Capabilities) => Promise; + +export type Screen = { + screenId: string; + description: string; + inputSchema: Schema; + events: EventDescriptor[]; +}; + +type EventDescriptor = { + eventId: string; + description: string; + /** + * The schema for the data that is dispatched along with the event. IF not + * present, there's no additional data supplied for this event. + */ + outputSchema?: Schema; +}; + +/** + * The Screen Server. Manages a set of pre-defined application screens and + * allows the application to render them and to obtain user inputs from those + * screens. + * + * For best results, call `getUserEvents` prior to `renderScreen` to capture any + * user events and then act on them to render the right screen. Combined + * together, `getUserEvents` and `renderScreen` form the rendering loop for the + * application UI. + */ +type ScreenServer = { + /** + * Gets the list of user events. Will block until it receives at least one + * user event. Accumulates and drains the queue of user events when called. + */ + getUserEvents(): Promise; + /** + * Updates screens with specified ids. This call does not block on user + * input. To collect user input from the screen, call `getUserEvents`. + * To make updates more efficiens, multiple screens can be updated in a + * single call. + * + * @param screenInputs -- the list of the screen inputs to update. + */ + updateScreens(screenInputs: ScreenInput[]): Promise; +}; + +type ScreenInput = { + screenId: string; + inputs: Record; +}; + +type GetUserEventsResponse = { + events: UserEvent[]; + isError: boolean; +}; + +type RenderScreenResponse = { + isError: boolean; +}; + +type UserEvent = { + screenId: string; + data: Record; +}; + +/** + * Access to Gemini API + */ +type Gemini = { + generateContent(args: GeminiInputs): Promise; +}; + +export type HarmBlockThreshold = + // Content with NEGLIGIBLE will be allowed. + | "BLOCK_LOW_AND_ABOVE" + // Content with NEGLIGIBLE and LOW will be allowed. + | "BLOCK_MEDIUM_AND_ABOVE" + // Content with NEGLIGIBLE, LOW, and MEDIUM will be allowed. + | "BLOCK_ONLY_HIGH" + // All content will be allowed. + | "BLOCK_NONE" + // Turn off the safety filter. + | "OFF"; + +export type HarmCategory = + // Gemini - Harassment content + | "HARM_CATEGORY_HARASSMENT" + // Gemini - Hate speech and content. + | "HARM_CATEGORY_HATE_SPEECH" + // Gemini - Sexually explicit content. + | "HARM_CATEGORY_SEXUALLY_EXPLICIT" + // Gemini - Dangerous content. + | "HARM_CATEGORY_DANGEROUS_CONTENT" + // Gemini - Content that may be used to harm civic integrity. + | "HARM_CATEGORY_CIVIC_INTEGRITY"; + +export type Modality = "TEXT" | "IMAGE" | "AUDIO"; + +export type GenerationConfig = { + responseMimeType?: "text/plain" | "application/json" | "text/x.enum"; + responseSchema?: Schema; + responseModalities?: Modality[]; +}; + +export type SafetySetting = { + category: HarmCategory; + threshold: HarmBlockThreshold; +}; + +export type FunctionCallPart = { + functionCall: { + name: string; + args: object; + }; +}; + +export type FunctionResponsePart = { + functionResponse: { + name: string; + response: object; + }; +}; + +export type TextPart = { + text: string; +}; + +export type DataStoreHandle = string; + +export type FileDataPart = { + fileData: { + /** + * Can be one of these three: + * - a URL pointing to a YT video + * - a URL pointing at a resource saved with File API. + * - a VFS path in the format of "/vfs/out/[guid]" + */ + fileUri: string; + mimeType: string; + resourceKey?: string; + }; +}; + +export type ExecutableCodePart = { + executableCode: { + language: "LANGUAGE_UNSPECIFIED" | "PYTHON"; + code: string; + }; +}; + +export type CodeExecutionResultOutcome = + // Unspecified status. This value should not be used. + | "OUTCOME_UNSPECIFIED" + // Code execution completed successfully. + | "OUTCOME_OK" + // Code execution finished but with a failure. stderr should contain the reason. + | "OUTCOME_FAILED" + // Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + | "OUTCOME_DEADLINE_EXCEEDED"; + +export type CodeExecutionResultPart = { + codeExecutionResult: { + outcome: CodeExecutionResultOutcome; + output: string; + }; +}; + +export type DataPart = + | InlineDataPart + | FileDataPart + | ExecutableCodePart + | CodeExecutionResultPart + | FunctionCallPart + | FunctionResponsePart + | TextPart; + +export type LLMContent = { + role?: string; + parts: DataPart[]; +}; + +/** + * Represents inline data, encoded as a base64 string. Use only for inputs. + * Outputs are always provided as FileData with VFS path. + */ +export type InlineDataPart = { + inlineData: { + mimeType: string; + data: string; + title?: string; + }; +}; + +export type GeminiBody = { + contents: LLMContent[]; + tools?: Tool[]; + toolConfig?: ToolConfig; + systemInstruction?: LLMContent; + safetySettings?: SafetySetting[]; + generationConfig?: GenerationConfig; +}; + +export type GeminiInputs = { + model?: string; + context?: LLMContent[]; + systemInstruction?: LLMContent; + prompt?: LLMContent; + body: GeminiBody; +}; + +export type Tool = { + functionDeclarations?: FunctionDeclaration[]; + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + googleSearch?: {}; + codeExecution?: CodeExecution; +}; + +export type ToolConfig = { + functionCallingConfig?: FunctionCallingConfig; +}; + +export type FunctionCallingConfig = { + mode?: "MODE_UNSPECIFIED" | "AUTO" | "ANY" | "NONE"; + allowedFunctionNames?: string[]; +}; + +export type FunctionDeclaration = { + name: string; + description: string; + parameters?: Schema; +}; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export type CodeExecution = { + // Type contains no fields. +}; + +export type FinishReason = + // Natural stop point of the model or provided stop sequence. + | "STOP" + // The maximum number of tokens as specified in the request was reached. + | "MAX_TOKENS" + // The response candidate content was flagged for safety reasons. + | "SAFETY" + // The response candidate content was flagged for image safety reasons. + | "IMAGE_SAFETY" + // The response candidate content was flagged for recitation reasons. + | "RECITATION" + // The response candidate content was flagged for using an unsupported language. + | "LANGUAGE" + // Unknown reason. + | "OTHER" + // Token generation stopped because the content contains forbidden terms. + | "BLOCKLIST" + // Token generation stopped for potentially containing prohibited content. + | "PROHIBITED_CONTENT" + // Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + | "SPII" + // The function call generated by the model is invalid. + | "MALFORMED_FUNCTION_CALL"; + +export type GroundingMetadata = { + groundingChunks: { + web: { + uri: string; + title: string; + }; + }[]; + groundingSupports: { + groundingChunkIndices: number[]; + confidenceScores: number[]; + segment: { + partIndex: number; + startIndex: number; + endIndex: number; + text: string; + }; + }; + webSearchQueries: string[]; + searchEntryPoint: { + renderedContent: string; + /** + * Base64 encoded JSON representing array of tuple. + * A base64-encoded string. + */ + sdkBlob: string; + }; + retrievalMetadata: { + googleSearchDynamicRetrievalScore: number; + }; +}; + +export type Candidate = { + /** + * The LLM output. + * IMPORTANT: Unlike the standard Gemini API, any media will be provided as + * the `FileDataPart` with the `fileUri` populated with the VFS file path. + * The VFS is the virtual file system that allows efficiently passing large + * media files within the application. The VFS paths are opaque identifiers + * for media files and can be provided as both inputs and outputs. The VFS + * files always start with "/vfs/". + */ + content?: LLMContent; + finishReason?: FinishReason; + safetyRatings?: SafetySetting[]; + tokenOutput: number; + groundingMetadata: GroundingMetadata; +}; + +export type GeminiOutputs = { + candidates: Candidate[]; +}; +``` + +Any files in this prompt will be provided to the program as "/vfs/in/file\_[x]" +files, where x is the index of the file provided. + +When providing files as outputs, output them as `FilePart` structures within the +`LLMContent`, passing the VFS paths as-is. + +Make sure to write Javascript, not Typescript. Output it in markdown code +fences. + +The following Gemini models are available: + +- `gemini-2.5-pro` - Enhanced thinking and reasoning, multimodal understanding, + advanced coding, and more +- `gemini-2.5-flash` - Adaptive thinking, cost efficiency +- `gemini-2.5-flash-image-preview` - Precise, conversational image generation + and editing diff --git a/experiments/screens/out/adventure-game.js b/experiments/screens/out/adventure-game.js new file mode 100644 index 00000000000..97665299f6f --- /dev/null +++ b/experiments/screens/out/adventure-game.js @@ -0,0 +1,423 @@ +/** + * Helper function to call a prompt that expects a JSON response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The parsed JSON response. + */ +export async function callJsonPrompt(generate, prompts, promptName, args = {}) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-pro", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + generationConfig: { + responseMimeType: "application/json", + responseSchema: prompt.responseSchema, + }, + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate content.`); + } + const textPart = candidate.content.parts.find((part) => "text" in part); + if (!textPart) { + throw new Error(`No text part in response for ${promptName}.`); + } + return JSON.parse(textPart.text); +} + +/** + * Helper function to call a prompt that expects a text response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The text response. + */ +export async function callTextPrompt(generate, prompts, promptName, args = {}) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-pro", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate content.`); + } + const textPart = candidate.content.parts.find((part) => "text" in part); + if (!textPart) { + throw new Error(`No text part in response for ${promptName}.`); + } + return textPart.text; +} + +/** + * Helper function to call a prompt that expects an image response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The VFS path to the generated image. + */ +export async function callImagePrompt( + generate, + prompts, + promptName, + args = {} +) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-flash-image-preview", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + generationConfig: { + responseModalities: ["IMAGE"], + }, + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate an image.`); + } + const filePart = candidate.content.parts.find((part) => "fileData" in part); + if (!filePart) { + throw new Error(`No image part in response for ${promptName}.`); + } + return filePart.fileData.fileUri; +} + + +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default async function (capabilities) { + const { mcp, console, generate, prompts } = capabilities; + + // Game state to hold the story, character, and player history + let gameState = { + plot: "", + characterBio: "", + characterImagePrompt: "", + history: [], + currentSceneText: "", + currentChoices: [], + }; + + /** + * Helper function to update a single screen. + * @param {string} screenId The ID of the screen to update. + * @param {object} inputs The input data for the screen. + */ + const updateScreen = async (screenId, inputs) => { + await mcp.callTool({ + name: "screens_update_screens", + arguments: { + screenInputs: [{ screenId, inputs }], + }, + }); + }; + + /** + * Resets the game state and displays the initial start screen. + */ + const showStartScreen = async () => { + gameState = { + plot: "", + characterBio: "", + characterImagePrompt: "", + history: [], + currentSceneText: "", + currentChoices: [], + }; + await updateScreen("start_game", {}); + await updateScreen("controls", { gameStatus: "Ready to begin" }); + }; + + /** + * Handles the initial game setup after the user provides inspiration. + * @param {string} inspiration The user's inspiration for the game. + */ + async function handleStartGame(inspiration) { + await updateScreen("controls", { + gameStatus: "Generating your adventure...", + }); + const { plot, characterBio, characterImagePrompt } = await callJsonPrompt( + generate, + prompts, + "generate-plot-and-character", + { inspiration } + ); + + gameState.plot = plot; + gameState.characterBio = characterBio; + gameState.characterImagePrompt = characterImagePrompt; + + const picture = await callImagePrompt( + generate, + prompts, + "generate-character-portrait", + { characterDescription: characterImagePrompt } + ); + + await updateScreen("choose_character", { bio: characterBio, picture }); + await updateScreen("controls", { gameStatus: "Choose your character" }); + } + + /** + * Handles the user's request to regenerate the character. + */ + async function handleRegenerateCharacter() { + await updateScreen("controls", { gameStatus: "Regenerating character..." }); + const { characterBio, characterImagePrompt } = await callJsonPrompt( + generate, + prompts, + "regenerate-character", + { plot: gameState.plot } + ); + + gameState.characterBio = characterBio; + gameState.characterImagePrompt = characterImagePrompt; + + const picture = await callImagePrompt( + generate, + prompts, + "generate-character-portrait", + { characterDescription: characterImagePrompt } + ); + + await updateScreen("choose_character", { bio: characterBio, picture }); + await updateScreen("controls", { gameStatus: "Choose your character" }); + } + + /** + * Generates and displays the next scene in the game. + */ + async function handleNewTurn() { + await updateScreen("controls", { gameStatus: "Generating next turn..." }); + + const historyString = + gameState.history.length > 0 + ? gameState.history.map((h, i) => `${i + 1}. ${h}`).join("\n") + : "No actions taken yet."; + + const { sceneText, sceneImagePrompt, choices } = await callJsonPrompt( + generate, + prompts, + "generate-next-turn", + { + plot: gameState.plot, + bio: gameState.characterBio, + history: historyString, + } + ); + + gameState.currentSceneText = sceneText; + gameState.currentChoices = choices; + + const image = await callImagePrompt( + generate, + prompts, + "generate-scene-image", + { + characterDescription: gameState.characterImagePrompt, + sceneDescription: sceneImagePrompt, + } + ); + + await updateScreen("scene", { + image, + text: sceneText, + choice1: choices[0], + choice2: choices[1], + choice3: choices[2], + choice4: choices[3], + }); + await updateScreen("controls", { gameStatus: "Your turn" }); + } + + /** + * Processes the player's choice, updates the plot, and determines the next step. + * @param {number} choiceIndex The 1-based index of the player's choice. + */ + async function handlePlayerChoice(choiceIndex) { + await updateScreen("controls", { gameStatus: "Processing your choice..." }); + + const choiceText = gameState.currentChoices[choiceIndex - 1]; + gameState.history.push(choiceText); + + const { updatedPlot, boonSecured } = await callJsonPrompt( + generate, + prompts, + "update-plot-based-on-choice", + { + plot: gameState.plot, + currentScene: gameState.currentSceneText, + choice: choiceText, + } + ); + + gameState.plot = updatedPlot; + + if (boonSecured) { + await handleFinale(); + } else { + await handleNewTurn(); + } + } + + /** + * Generates and displays the final, celebratory scene of the game. + */ + async function handleFinale() { + await updateScreen("controls", { + gameStatus: "Generating the grand finale...", + }); + + const { finaleText, finaleImagePrompt } = await callJsonPrompt( + generate, + prompts, + "generate-finale", + { + plot: gameState.plot, + bio: gameState.characterBio, + } + ); + + const image = await callImagePrompt( + generate, + prompts, + "generate-scene-image", + { + characterDescription: gameState.characterImagePrompt, + sceneDescription: finaleImagePrompt, + } + ); + + await updateScreen("finale", { image, text: finaleText }); + await updateScreen("controls", { gameStatus: "Congratulations!" }); + } + + /** + * Displays a recap of the player's journey so far. + */ + async function handleRecap() { + const recapText = + gameState.history.length > 0 + ? `**Your Story So Far:**\n\n` + + gameState.history + .map( + (h, i) => + `${i + 1}. You chose to ${h.charAt(0).toLowerCase() + h.slice(1)}` + ) + .join("\n") + : "Your adventure has just begun! No choices have been made yet."; + + await updateScreen("game_recap", { recap: recapText }); + } + + // Initial call to set up the game + await showStartScreen(); + + // Main game loop to process user events + while (true) { + const { response, isError } = await mcp.callTool({ + name: "screens_get_user_events", + }); + + if (isError || !response || !response.events) { + console.error("Error getting user events."); + continue; + } + + for (const event of response.events) { + const { screenId, eventId, output } = event; + + switch (screenId) { + case "start_game": + if (eventId === "generate_inspiration") { + await updateScreen("controls", { + gameStatus: "Generating inspiration...", + }); + const inspiration = await callTextPrompt( + generate, + prompts, + "generate-inspiration" + ); + await updateScreen("start_game", { + generatedInspiration: inspiration, + }); + await updateScreen("controls", { gameStatus: "Ready to begin" }); + } else if (eventId === "start") { + await handleStartGame(output.inspiration); + } + break; + + case "choose_character": + if (eventId === "regenerate") { + await handleRegenerateCharacter(); + } else if (eventId === "choose") { + await handleNewTurn(); + } + break; + + case "scene": + if (eventId === "choose") { + await handlePlayerChoice(output.choice); + } + break; + + case "finale": + if (eventId === "restart") { + await showStartScreen(); + } + break; + + case "controls": + if (eventId === "recap_game") { + await handleRecap(); + } + break; + } + } + } +} diff --git a/experiments/screens/out/ai-slop-or-not.js b/experiments/screens/out/ai-slop-or-not.js new file mode 100644 index 00000000000..de945baf157 --- /dev/null +++ b/experiments/screens/out/ai-slop-or-not.js @@ -0,0 +1,304 @@ +/** + * Helper function to call a prompt that expects a JSON response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The parsed JSON response. + */ +export async function callJsonPrompt(generate, prompts, promptName, args = {}) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-pro", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + generationConfig: { + responseMimeType: "application/json", + responseSchema: prompt.responseSchema, + }, + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate content.`); + } + const textPart = candidate.content.parts.find((part) => "text" in part); + if (!textPart) { + throw new Error(`No text part in response for ${promptName}.`); + } + return JSON.parse(textPart.text); +} + +/** + * Helper function to call a prompt that expects a text response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The text response. + */ +export async function callTextPrompt(generate, prompts, promptName, args = {}) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-pro", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate content.`); + } + const textPart = candidate.content.parts.find((part) => "text" in part); + if (!textPart) { + throw new Error(`No text part in response for ${promptName}.`); + } + return textPart.text; +} + +/** + * Helper function to call a prompt that expects an image response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The VFS path to the generated image. + */ +export async function callImagePrompt( + generate, + prompts, + promptName, + args = {} +) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-flash-image-preview", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + generationConfig: { + responseModalities: ["IMAGE"], + }, + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate an image.`); + } + const filePart = candidate.content.parts.find((part) => "fileData" in part); + if (!filePart) { + throw new Error(`No image part in response for ${promptName}.`); + } + return filePart.fileData.fileUri; +} + + +/** + * @license + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default async function({ + mcp, + prompts, + generate, + console +}) { + // Main game loop to allow for "Play Again" functionality. + while (true) { + // 1. START: Display the start screen and wait for the user to provide a topic. + await mcp.callTool({ + name: 'screens_update_screens', + arguments: { + screenInputs: [{ + screenId: 'start_screen', + inputs: {} + }], + }, + }); + + let userEventResponse = await mcp.callTool({ + name: 'screens_get_user_events', + arguments: {}, + }); + const startEvent = userEventResponse.response.events[0]; + + // Ensure we handle the correct event before starting. + if (startEvent.eventId !== 'start_game' || !startEvent.output.topic) { + console.error('Expected a start_game event with a topic, but got:', startEvent); + // In a real app, you might want to show an error screen. Here, we'll just exit. + return { + parts: [{ + text: 'Error: Invalid start event.' + }] + }; + } + const topic = startEvent.output.topic; + console.log(`Game started with topic: "${topic}"`); + + // Initialize game state. + let roundNumber = 1; + const TOTAL_ROUNDS = 10; + // Use an object to track each image's VFS path and its survival count. + const imageSurvivalData = {}; + + // 2. INITIAL ROUND: Generate the first two images. + console.log('Generating initial images for Round 1...'); + const imageAPath = await callImagePrompt(generate, prompts, 'generate-image', { + topic + }); + const imageBPath = await callImagePrompt(generate, prompts, 'generate-image', { + topic + }); + + imageSurvivalData[imageAPath] = { + survivalCount: 0 + }; + imageSurvivalData[imageBPath] = { + survivalCount: 0 + }; + + let currentChampionPath = imageAPath; + let currentChallengerPath = imageBPath; + + // 3. GAME LOOP: Run for the specified number of rounds. + while (roundNumber <= TOTAL_ROUNDS) { + console.log(`--- Round ${roundNumber} ---`); + + // Present the two images to the user. + await mcp.callTool({ + name: 'screens_update_screens', + arguments: { + screenInputs: [{ + screenId: 'game_screen', + inputs: { + roundNumber: roundNumber, + imageA: currentChampionPath, + imageB: currentChallengerPath, + }, + }, ], + }, + }); + + // Wait for the user to choose their preferred image. + userEventResponse = await mcp.callTool({ + name: 'screens_get_user_events', + arguments: {}, + }); + const choiceEvent = userEventResponse.response.events[0]; + const userChoice = choiceEvent.output.choice; + + // Determine the winner of the round. + const winnerPath = userChoice === 'A' ? currentChampionPath : currentChallengerPath; + console.log(`User chose image ${userChoice}. Winner: ${winnerPath}`); + + // Increment the winner's survival counter. + imageSurvivalData[winnerPath].survivalCount++; + + // The winner advances to the next round. + currentChampionPath = winnerPath; + + // If it's not the last round, generate a new challenger. + if (roundNumber < TOTAL_ROUNDS) { + console.log('Generating new challenger for the next round...'); + currentChallengerPath = await callImagePrompt(generate, prompts, 'generate-image', { + topic + }); + // Add the new challenger to our tracking data. + if (!imageSurvivalData[currentChallengerPath]) { + imageSurvivalData[currentChallengerPath] = { + survivalCount: 0 + }; + } + } + + // Move to the next round. + roundNumber++; + } + + // 4. END GAME: The loop has finished. + console.log('--- Game Over ---'); + + // 5. WINNER SCREEN: Find the image that survived the most rounds. + let finalWinnerPath = ''; + let maxSurvival = -1; + + for (const path in imageSurvivalData) { + if (imageSurvivalData[path].survivalCount > maxSurvival) { + maxSurvival = imageSurvivalData[path].survivalCount; + finalWinnerPath = path; + } + } + + console.log(`Final winner is ${finalWinnerPath} with ${maxSurvival} wins.`); + + // Display the winner. + await mcp.callTool({ + name: 'screens_update_screens', + arguments: { + screenInputs: [{ + screenId: 'winner_screen', + inputs: { + winnerText: `Winner! This image survived ${maxSurvival} rounds.`, + winningImage: finalWinnerPath, + }, + }, ], + }, + }); + + // Wait for the user to decide if they want to play again. + userEventResponse = await mcp.callTool({ + name: 'screens_get_user_events', + arguments: {}, + }); + const endEvent = userEventResponse.response.events[0]; + + // If the user doesn't want to play again, break the main loop. + if (endEvent.eventId !== 'play_again') { + console.log('User chose not to play again. Exiting.'); + break; + } + + console.log('User wants to play again. Resetting game.'); + // The `while(true)` loop will now restart the game from the beginning. + } + + // The application will terminate after this function returns. + return { + parts: [{ + text: 'Thank you for playing AI Slop or Not!' + }] + }; +} diff --git a/experiments/screens/out/blog-post-writer.js b/experiments/screens/out/blog-post-writer.js new file mode 100644 index 00000000000..4cd8a82cc2e --- /dev/null +++ b/experiments/screens/out/blog-post-writer.js @@ -0,0 +1,282 @@ +/** + * Helper function to call a prompt that expects a JSON response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The parsed JSON response. + */ +export async function callJsonPrompt(generate, prompts, promptName, args = {}) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-pro", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + generationConfig: { + responseMimeType: "application/json", + responseSchema: prompt.responseSchema, + }, + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate content.`); + } + const textPart = candidate.content.parts.find((part) => "text" in part); + if (!textPart) { + throw new Error(`No text part in response for ${promptName}.`); + } + return JSON.parse(textPart.text); +} + +/** + * Helper function to call a prompt that expects a text response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The text response. + */ +export async function callTextPrompt(generate, prompts, promptName, args = {}) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-pro", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate content.`); + } + const textPart = candidate.content.parts.find((part) => "text" in part); + if (!textPart) { + throw new Error(`No text part in response for ${promptName}.`); + } + return textPart.text; +} + +/** + * Helper function to call a prompt that expects an image response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The VFS path to the generated image. + */ +export async function callImagePrompt( + generate, + prompts, + promptName, + args = {} +) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-flash-image-preview", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + generationConfig: { + responseModalities: ["IMAGE"], + }, + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate an image.`); + } + const filePart = candidate.content.parts.find((part) => "fileData" in part); + if (!filePart) { + throw new Error(`No image part in response for ${promptName}.`); + } + return filePart.fileData.fileUri; +} + + +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default async (capabilities) => { + const { mcp, generate, prompts, console } = capabilities; + + // Start by showing the initial topic input screen. + await mcp.callTool({ + name: "screens_update_screens", + arguments: { + screenInputs: [ + { + screenId: "get_topic", + inputs: {}, + }, + ], + }, + }); + + // Main event loop to wait for and handle user interactions. + while (true) { + const userEventsResponse = await mcp.callTool({ + name: "screens_get_user_events", + arguments: {}, + }); + + for (const event of userEventsResponse.response.events) { + switch (event.eventId) { + case "write_post": { + if (event.screenId === "get_topic") { + const topic = event.output.topic; + console.log(`Starting blog post generation for topic: "${topic}"`); + + // 1. Show the "in progress" screen while researching. + await mcp.callTool({ + name: "screens_update_screens", + arguments: { + screenInputs: [ + { + screenId: "writing_in_progress", + inputs: { + status: "Researching topic and creating outline...", + }, + }, + ], + }, + }); + + // 2. Research the topic and generate an outline. + const researchAndOutline = await callJsonPrompt( + generate, + prompts, + "create-outline", + { topic } + ); + const researchAndOutlineJson = JSON.stringify(researchAndOutline); + console.log("Outline and research complete."); + + // 3. Update status to reflect the next steps. + await mcp.callTool({ + name: "screens_update_screens", + arguments: { + screenInputs: [ + { + screenId: "writing_in_progress", + inputs: { + status: + "Generating header graphic and writing the post...", + }, + }, + ], + }, + }); + + // 4. Start the parallel tasks: writing the post and generating the graphic. + console.log("Starting parallel tasks: writing post and generating image."); + + // Task A: Write the blog post. + const blogPostPromise = callTextPrompt( + generate, + prompts, + "write-blog-post", + { research_and_outline_json: researchAndOutlineJson } + ); + + // Task B: Generate the header graphic (this is a two-step process). + const headerGraphicPromise = callJsonPrompt( + generate, + prompts, + "create-image-prompt", + { research_and_outline_json: researchAndOutlineJson } + ).then((imagePromptResult) => { + console.log("Image prompt created, now generating image."); + return callImagePrompt( + generate, + prompts, + "generate-header-graphic", + { prompt: imagePromptResult.image_prompt } + ); + }); + + // 5. Wait for both parallel tasks to complete. + const [blog_post, header_graphic] = await Promise.all([ + blogPostPromise, + headerGraphicPromise, + ]); + console.log("All tasks completed."); + + // 6. Display the final result. + await mcp.callTool({ + name: "screens_update_screens", + arguments: { + screenInputs: [ + { + screenId: "show_result", + inputs: { + blog_post, + header_graphic, + }, + }, + ], + }, + }); + } + break; + } + + case "start_over": { + if (event.screenId === "show_result") { + console.log("Starting over."); + // Reset the application to the initial screen. + await mcp.callTool({ + name: "screens_update_screens", + arguments: { + screenInputs: [ + { + screenId: "get_topic", + inputs: {}, + }, + ], + }, + }); + } + break; + } + + default: { + console.log(`Unknown event: ${event.eventId}`); + break; + } + } + } + } +}; diff --git a/experiments/screens/package.json b/experiments/screens/package.json new file mode 100644 index 00000000000..044b8c2c788 --- /dev/null +++ b/experiments/screens/package.json @@ -0,0 +1,26 @@ +{ + "name": "screens", + "private": true, + "version": "1.0.0", + "main": "index.js", + "type": "module", + "scripts": { + "generate": "tsx src/generate.ts", + "screenify": "tsx src/screenify.ts", + "dev": "vite dev", + "test": "tsx test/adventure-game.test.ts" + }, + "keywords": [], + "author": "", + "license": "Apache-2.0", + "description": "", + "devDependencies": { + "tsx": "^4.20.6" + }, + "dependencies": { + "@google/genai": "^1.27.0", + "dotenv": "^17.2.3", + "lit": "^3.3.1", + "vite": "^7.2.6" + } +} diff --git a/experiments/screens/src/apps/adventure-game.ts b/experiments/screens/src/apps/adventure-game.ts new file mode 100644 index 00000000000..c57768f4882 --- /dev/null +++ b/experiments/screens/src/apps/adventure-game.ts @@ -0,0 +1,455 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Screen, Prompt } from "../types"; + +export const spec = ` +Make a turn-based adventure game. + +First +- user enters inspiration for the game +- the initial plot line of the game is generated, inventing the character and the story and the objective (the boon, in hero's journey terms) of the story. +- the user is presented with bio and picture of their character. To create a picture, a detailed text prompt of the character suitable for an image generation is generated as well. +- the user can decide to accept the character or re-generate a new one +- once the user accepts, the game begins + +For each turn: +- present the user with a generated picture of the scene that follows the plot of the game, along with: + - brief text description of what is happening in the scene + - four choices for the user on what they could do next +- the user makes a choice +- based on the choice the user made, update the plot of the game ensuring that there's a path to the boon for the user. + +Once the user secures the boon, show a celebratory screen that includes a generated picture of the final scene and a text that describes that scene.`; + +export const screens: Screen[] = [ + { + screenId: "controls", + description: "Displays game status and game controls", + inputSchema: { + type: "object", + properties: { + gameStatus: { + type: "string", + description: + 'A short sentence that describes current game status, like "Saving game state" or "Generating next turn"', + }, + }, + required: ["gameStatus"], + }, + events: [ + { + eventId: "recap_game", + description: + "Indicates that the user requested to recap the game so far", + }, + ], + }, + { + screenId: "game_recap", + description: "Displays recap of the game so far", + inputSchema: { + type: "object", + properties: { + recap: { + type: "string", + description: "Recap of the game so far, in markdown", + }, + }, + required: ["recap"], + }, + events: [], + }, + { + screenId: "start_game", + description: + "Shows at the start of the game, allowing the user to specify the inspiration for the game or ask to generate the inspration.", + inputSchema: { + type: "object", + properties: { + generatedInspiration: { + type: "string", + description: + "The optional generated inspiration for the game, provided upon user request", + }, + }, + }, + events: [ + { + eventId: "generate_inspiration", + description: + "Indicates that the user requested to generate an inspiration and pre-fill it for them", + }, + { + eventId: "start", + description: "Indicates that the user chose to start the game", + outputSchema: { + type: "object", + properties: { + inspiration: { + type: "string", + description: + "The inspiration for the game. Will be used to generate the character, the setting, and the initial plot of the game.", + }, + }, + required: ["inspiration"], + }, + }, + ], + }, + { + screenId: "choose_character", + description: + "Presents the user with a generated picture and bio of the character they will play, allowing the user to regenerate a different character until they find what they like.", + inputSchema: { + type: "object", + properties: { + bio: { + type: "string", + description: "The generated bio of the player's character", + }, + picture: { + type: "string", + description: + "The VFS path to generated picture of the player's character", + }, + }, + required: ["bio", "picture"], + }, + events: [ + { + eventId: "regenerate", + description: "Indicates that the user decided to regenerate the game", + }, + { + eventId: "choose", + description: "Indicates that the user chose the provided character", + }, + ], + }, + { + screenId: "scene", + description: + "Show the user the current scene (aka the turn) of the game and allows the user to select one of four options for what to do next", + inputSchema: { + type: "object", + properties: { + image: { + type: "string", + description: "The VFS path to generated scene image", + }, + text: { + type: "string", + description: + "A brief description of what is happening in the scene to help the user orient and make the next choice", + }, + choice1: { + type: "string", + description: "Text of the first choice for the user to select", + }, + choice2: { + type: "string", + description: "Text of the second choice for the user to select", + }, + choice3: { + type: "string", + description: "Text of the third choice for the user to select", + }, + choice4: { + type: "string", + description: "Text of the fourth choice for the user to select", + }, + }, + required: ["image", "text", "choice1", "choice2", "choice3", "choice4"], + }, + events: [ + { + eventId: "choose", + description: + "Indicates that the user has made their choice for this scene", + outputSchema: { + type: "object", + properties: { + choice: { + type: "number", + description: "The 1-based index of the choice (1, 2, 3, or 4)", + }, + }, + required: ["choice"], + }, + }, + ], + }, + { + screenId: "finale", + description: + "Show the user the final scene of the game and allows the user to start a new game", + inputSchema: { + type: "object", + properties: { + image: { + type: "string", + description: "The VFS path to generated scene image", + }, + text: { + type: "string", + description: + "A brief description of what is happening in the scene to help the user orient and make the next choice", + }, + }, + required: ["image", "text"], + }, + events: [ + { + eventId: "restart", + description: "Indicates that the user has decide to restart the game", + }, + ], + }, +]; + +export const prompts: Prompt[] = [ + { + name: "generate-inspiration", + description: + "Generate a one-sentence inspiration for a fantasy adventure game.", + format: "text", + value: "Generate a one-sentence inspiration for a fantasy adventure game.", + }, + { + name: "generate-plot-and-character", + description: "Generate the initial plot and character for the game.", + format: "json", + arguments: [ + { + name: "inspiration", + description: "The user's inspiration for the game.", + required: true, + }, + ], + responseSchema: { + type: "object", + properties: { + plot: { + type: "string", + description: "The initial plot, world, and objective.", + }, + characterBio: { + type: "string", + description: "The character's biography.", + }, + characterImagePrompt: { + type: "string", + description: "A detailed prompt for image generation.", + }, + }, + required: ["plot", "characterBio", "characterImagePrompt"], + }, + value: `You are a master storyteller creating a new turn-based adventure game. The user's inspiration is: "{{inspiration}}". Generate the initial setup: a compelling character, a rich world, and a clear objective (the 'boon'). Respond with a JSON object matching the provided schema.`, + }, + { + name: "regenerate-character", + description: "Regenerate the character for the game.", + format: "json", + arguments: [ + { + name: "plot", + description: "The current plot of the game.", + required: true, + }, + ], + responseSchema: { + type: "object", + properties: { + characterBio: { + type: "string", + description: "A new, different character's biography.", + }, + characterImagePrompt: { + type: "string", + description: "A detailed prompt for the new character's image.", + }, + }, + required: ["characterBio", "characterImagePrompt"], + }, + value: `You are a master storyteller creating a character for an adventure game. The plot is set: "{{plot}}". Generate a NEW, different character bio and image prompt for this story. Respond with a JSON object matching the provided schema.`, + }, + { + name: "generate-scene-image", + description: "Generates the scene image", + format: "image", + arguments: [ + { + name: "characterDescription", + description: + "Detailed description of the main character's visual features", + required: true, + }, + { + name: "sceneDescription", + description: "Detailed description of the scene", + required: true, + }, + ], + value: `Generate stylized art for a video game, depicting a scene with a character in it. + ## Scene Description + {{sceneDescription}} + + ## Character Description + {{characterDescription}}`, + }, + { + name: "generate-character-portrait", + description: "Generates the character portrait", + format: "image", + arguments: [ + { + name: "characterDescription", + description: + "Detailed description of the main character's visual features", + required: true, + }, + ], + value: `Generate stylized art for a video game, depicting the main character of the game as a full-body portrait. + + ## Character Description + {{characterDescription}}`, + }, + { + name: "generate-next-turn", + description: "Generate the next turn of the game.", + format: "json", + arguments: [ + { + name: "plot", + description: "The current plot of the game.", + required: true, + }, + { + name: "bio", + description: "The character's biography.", + required: true, + }, + { + name: "history", + description: "The history of the player's actions.", + required: true, + }, + ], + responseSchema: { + type: "object", + properties: { + sceneText: { + type: "string", + description: "A brief description of the current scene.", + }, + sceneImagePrompt: { + type: "string", + description: "A detailed prompt for the scene's image.", + }, + choices: { + type: "array", + items: { + type: "string", + }, + minItems: 4, + maxItems: 4, + description: "Four possible actions for the player.", + }, + }, + required: ["sceneText", "sceneImagePrompt", "choices"], + }, + value: `You are the Dungeon Master for a turn-based adventure game. + **The Story So Far:** + {{plot}} + **Character:** + {{bio}} + **Player History:** + {{history}} + Generate the next scene. It must logically follow the story and present the player with four meaningful, distinct choices. Respond with a JSON object matching the provided schema.`, + }, + { + name: "update-plot-based-on-choice", + description: "Update the plot based on the user's choice.", + format: "json", + arguments: [ + { + name: "plot", + description: "The current plot of the game.", + required: true, + }, + { + name: "currentScene", + description: "The text of the current scene.", + required: true, + }, + { + name: "choice", + description: "The player's choice.", + required: true, + }, + ], + responseSchema: { + type: "object", + properties: { + updatedPlot: { + type: "string", + description: "The new plot incorporating the choice's outcome.", + }, + boonSecured: { + type: "boolean", + description: "True if the main objective is now complete.", + }, + }, + required: ["updatedPlot", "boonSecured"], + }, + value: `You are the Dungeon Master, updating the story based on the player's actions. + **The Story So Far:** + {{plot}} + **Current Scene:** + {{currentScene}} + **Player's Choice:** + {{choice}} + Now, write the next part of the story. Describe the outcome and advance the plot toward the objective. Determine if this action results in securing the boon. Respond with a JSON object matching the provided schema.`, + }, + { + name: "generate-finale", + description: "Generate the finale of the game.", + format: "json", + arguments: [ + { + name: "plot", + description: "The final plot of the game.", + required: true, + }, + { + name: "bio", + description: "The character's biography.", + required: true, + }, + ], + responseSchema: { + type: "object", + properties: { + finaleText: { + type: "string", + description: "Celebratory text for the final scene.", + }, + finaleImagePrompt: { + type: "string", + description: "A detailed prompt for the final image.", + }, + }, + required: ["finaleText", "finaleImagePrompt"], + }, + value: `You are the Dungeon Master. The player has won! + **Final Story State:** + {{plot}} + **The Hero:** + {{bio}} + Write the final, celebratory scene. Describe the hero's triumph. This is the epilogue. Respond with a JSON object matching the provided schema.`, + }, +]; diff --git a/experiments/screens/src/apps/ai-slop-or-not.ts b/experiments/screens/src/apps/ai-slop-or-not.ts new file mode 100644 index 00000000000..1d2652f0ddc --- /dev/null +++ b/experiments/screens/src/apps/ai-slop-or-not.ts @@ -0,0 +1,135 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Screen, Prompt } from "../types"; + +export const spec = ` +Create a game called "AI Slop or Not". + +1. **Start**: The application will first ask the user to provide a topic for image generation. +2. **Initial Round**: Once the topic is submitted, the application will generate two images based on that topic. +3. **Game Loop (10 Rounds)**: + * The user is presented with the two images and the current round number. + * The user must choose which of the two images is better (i.e., "not slop"). + * The image that was *not* chosen (the "loser") is discarded. + * The image that was chosen (the "winner") advances to the next round. A counter for this image's "survival" is incremented. + * A new image is generated based on the original topic to compete against the previous round's winner. + * This continues for a total of 10 rounds. +4. **End Game**: After 10 rounds, the game ends. +5. **Winner Screen**: The application identifies the single image that survived the most rounds. This image is displayed to the user with a "Winner" message. The user is then given the option to play again. +`; + +export const screens: Screen[] = [ + { + screenId: "start_screen", + description: + "The initial screen where the user enters a topic for the image generation game.", + inputSchema: { + type: "object", + properties: {}, + }, + events: [ + { + eventId: "start_game", + description: "Starts the game with the provided topic.", + outputSchema: { + type: "object", + properties: { + topic: { + type: "string", + description: "The topic for the images to be generated.", + }, + }, + required: ["topic"], + }, + }, + ], + }, + { + screenId: "game_screen", + description: + "Displays two images for the user to choose from and shows the current round number.", + inputSchema: { + type: "object", + properties: { + roundNumber: { + type: "number", + description: "The current round number, from 1 to 10.", + }, + imageA: { + type: "string", + description: "VFS path to the first image for comparison.", + }, + imageB: { + type: "string", + description: "VFS path to the second image for comparison.", + }, + }, + required: ["roundNumber", "imageA", "imageB"], + }, + events: [ + { + eventId: "choose", + description: "Event fired when the user chooses their preferred image.", + outputSchema: { + type: "object", + properties: { + choice: { + type: "string", + enum: ["A", "B"], + description: + "The image chosen by the user, corresponding to imageA or imageB.", + }, + }, + required: ["choice"], + }, + }, + ], + }, + { + screenId: "winner_screen", + description: + "Displays the final winning image after 10 rounds of competition.", + inputSchema: { + type: "object", + properties: { + winnerText: { + type: "string", + description: "A celebratory message, like 'Winner!'", + }, + winningImage: { + type: "string", + description: "VFS path to the image that survived the most rounds.", + }, + }, + required: ["winnerText", "winningImage"], + }, + events: [ + { + eventId: "play_again", + description: + "Indicates the user wants to start a new game, returning them to the start screen.", + }, + ], + }, +]; + +export const prompts: Prompt[] = [ + { + name: "generate-image", + description: "Generates an image based on a user-provided topic.", + format: "image", + arguments: [ + { + name: "topic", + description: "The subject for the image generation.", + required: true, + }, + ], + value: + "A vibrant, high-detail, artistic masterpiece digital painting of the following topic: {{topic}}. Cinematic lighting, epic composition, visually stunning.", + }, +]; diff --git a/experiments/screens/src/apps/blog-post-writer.ts b/experiments/screens/src/apps/blog-post-writer.ts new file mode 100644 index 00000000000..48bb41eca19 --- /dev/null +++ b/experiments/screens/src/apps/blog-post-writer.ts @@ -0,0 +1,205 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Screen, Prompt } from "../types"; + +export const spec = ` +Make a blog post writer. It takes a topic, then does some research on it, then writes an outline, then generates an snazzy header graphic based on this outline, and in parallel, writes the blog post based on the outline. Then shows the header graphic and the blog post as a final result. +`; + +export const screens: Screen[] = [ + { + screenId: "get_topic", + description: "Prompts the user to enter a topic for the blog post.", + inputSchema: { + type: "object", + properties: {}, + }, + events: [ + { + eventId: "write_post", + description: "User submits a topic to start the writing process.", + outputSchema: { + type: "object", + properties: { + topic: { + type: "string", + description: "The topic for the blog post.", + }, + }, + required: ["topic"], + }, + }, + ], + }, + { + screenId: "writing_in_progress", + description: "Displays the progress of the blog post generation.", + inputSchema: { + type: "object", + properties: { + status: { + type: "string", + description: + "A message indicating the current step, e.g., 'Researching topic...', 'Generating outline...', 'Writing post...'", + }, + }, + required: ["status"], + }, + events: [], + }, + { + screenId: "show_result", + description: "Displays the final generated blog post and header graphic.", + inputSchema: { + type: "object", + properties: { + header_graphic: { + type: "string", + description: "VFS path to the generated header graphic.", + }, + blog_post: { + type: "string", + description: "The full blog post content in Markdown format.", + }, + }, + required: ["header_graphic", "blog_post"], + }, + events: [ + { + eventId: "start_over", + description: "User wants to write a new blog post.", + }, + ], + }, +]; + +export const prompts: Prompt[] = [ + { + name: "create-outline", + description: + "Researches a topic and creates a structured outline and research summary for a blog post.", + format: "json", + arguments: [ + { + name: "topic", + description: "The topic for the blog post.", + required: true, + }, + ], + responseSchema: { + type: "object", + properties: { + title: { + type: "string", + description: "A compelling title for the blog post.", + }, + research_summary: { + type: "string", + description: + "A concise summary of the key findings from the research on the topic. This will be used to inform the writing process.", + }, + outline: { + type: "object", + properties: { + introduction: { + type: "string", + description: + "A bullet point or short sentence for the introduction's main theme.", + }, + sections: { + type: "array", + items: { + type: "object", + properties: { + heading: { + type: "string", + description: + "The heading for this section of the blog post.", + }, + points: { + type: "array", + items: { + type: "string", + }, + description: + "An array of key points or sub-topics to cover in this section.", + }, + }, + required: ["heading", "points"], + }, + }, + conclusion: { + type: "string", + description: + "A bullet point or short sentence for the conclusion's main message.", + }, + }, + required: ["introduction", "sections", "conclusion"], + }, + }, + required: ["title", "research_summary", "outline"], + }, + value: + 'You are a research assistant and content strategist. Your task is to research the given topic and create a comprehensive plan for a blog post. \n\nTopic: "{{topic}}"\n\nFirst, perform research to gather key information, facts, and different perspectives on the topic. Then, based on your research, generate a JSON object that includes a catchy title, a summary of your research findings, and a detailed outline for the blog post. The outline should have an introduction, multiple sections with headings and bullet points, and a conclusion. Use built-in search tool to do the research', + }, + { + name: "create-image-prompt", + description: + "Creates a detailed, artistic prompt for an image generation model based on a blog post outline and research.", + format: "json", + arguments: [ + { + name: "research_and_outline_json", + description: + "The JSON object containing the title, research summary, and outline.", + required: true, + }, + ], + responseSchema: { + type: "object", + properties: { + image_prompt: { + type: "string", + description: + "A detailed, artistic, and visually rich prompt for generating a header image.", + }, + }, + required: ["image_prompt"], + }, + value: + "You are a creative director. Based on the following blog post plan, create a single, concise, yet evocative and visually rich prompt for an AI image generator to create a header graphic. The prompt should capture the main theme and tone of the article. Respond with a JSON object containing the `image_prompt`.\n\nBlog Post Plan:\n{{research_and_outline_json}}", + }, + { + name: "generate-header-graphic", + description: "Generates a header graphic for a blog post.", + format: "image", + arguments: [ + { + name: "prompt", + description: "The detailed, artistic prompt for the image generator.", + required: true, + }, + ], + value: "{{prompt}}", + }, + { + name: "write-blog-post", + description: + "Writes a full blog post based on a provided outline and research summary.", + format: "text", + arguments: [ + { + name: "research_and_outline_json", + description: + "The JSON object containing the title, research summary, and outline.", + required: true, + }, + ], + value: + "You are an expert blog writer. Your task is to write a comprehensive, engaging, and well-structured blog post based on the provided plan. Use Markdown for formatting. Ensure the tone is appropriate for the topic and that the content flows logically from one section to the next.\n\nBlog Post Plan:\n{{research_and_outline_json}}\n\nNow, write the full blog post.", + }, +]; diff --git a/experiments/screens/src/capabilities.ts b/experiments/screens/src/capabilities.ts new file mode 100644 index 00000000000..c6e62127bfb --- /dev/null +++ b/experiments/screens/src/capabilities.ts @@ -0,0 +1,233 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + Content, + ContentUnion, + GoogleGenAI, + Tool, + ToolConfig, +} from "@google/genai"; +import { + Candidate, + GetUserEventsResponse, + UserEvent, + Capabilities, + GeminiInputs, + CallToolRequest, + ScreenInput, + Prompt, + SchemaValidated, +} from "./types"; +import { screens, prompts } from "./apps/blog-post-writer"; +import { TestHarness } from "./ui/test-harness"; + +const GEMINI_KEY = import.meta.env.VITE_GEMINI_KEY; + +const promptMap = new Map( + prompts.map((prompt) => [prompt.name, prompt]) +); + +class EventQueue { + resolve: ((response: GetUserEventsResponse) => void) | null = null; + queue: UserEvent[] = []; + + add(event: UserEvent) { + this.queue.push(event); + if (!this.resolve) return; + const events = [...this.queue]; + this.queue.length = 0; + const resolve = this.resolve; + this.resolve = null; + resolve({ + events, + isError: false, + }); + } + + async get(): Promise { + if (this.queue.length === 0) { + return new Promise((resolve) => { + this.resolve = resolve; + }); + } + const events = [...this.queue]; + this.queue.length = 0; + return { + events, + isError: false, + }; + } +} + +export class CapabilitiesImpl implements Capabilities { + readonly eventQueue = new EventQueue(); + #testHarness: TestHarness | null = null; + #log: unknown[][] = []; + #vfs = new Map(); + + constructor() { + document.body.addEventListener("user-event", (e) => { + const event = (e as CustomEvent).detail; + this.#log = [...this.#log, ["User event:", event]]; + this.eventQueue.add(event); + }); + } + + #logToConsole(...params: unknown[]) { + this.#log = [...this.#log, params]; + if (this.#testHarness) { + this.#testHarness.log = this.#log; + } + } + + #processInlineData(candidates: Candidate[]): Candidate[] { + return candidates.map((candidate) => { + if (!candidate.content || !candidate.content.parts) { + return candidate; + } + + const parts = candidate.content.parts.map((part) => { + if (!("inlineData" in part)) { + return part; + } + + const { mimeType, data } = part.inlineData; + const byteCharacters = atob(data); + const byteNumbers = new Array(byteCharacters.length); + for (let i = 0; i < byteCharacters.length; i++) { + byteNumbers[i] = byteCharacters.charCodeAt(i); + } + const byteArray = new Uint8Array(byteNumbers); + const blob = new Blob([byteArray], { type: mimeType }); + const blobUrl = URL.createObjectURL(blob); + const vfsPath = `/vfs/out/${crypto.randomUUID()}`; + this.#vfs.set(vfsPath, blobUrl); + return { + fileData: { + fileUri: vfsPath, + mimeType, + }, + }; + }); + + return { ...candidate, content: { ...candidate.content, parts } }; + }); + } + + generate = { + generateContent: async (args: GeminiInputs) => { + this.#logToConsole("Calling generateContent:", args); + const gemini = new GoogleGenAI({ apiKey: GEMINI_KEY }); + const result = await gemini.models.generateContent({ + model: args.model ?? "gemini-2.5-flash", + contents: args.contents as Content, + config: { + tools: args.tools as Tool[], + toolConfig: args.toolConfig as ToolConfig, + responseSchema: args.generationConfig?.responseSchema, + responseMimeType: args.generationConfig?.responseMimeType, + systemInstruction: args.systemInstruction as ContentUnion, + responseModalities: args.generationConfig?.responseModalities, + }, + }); + this.#logToConsole("generateContent returned:", result); + return { + candidates: this.#processInlineData(result.candidates as Candidate[]), + }; + }, + }; + mcp = { + callTool: async (params: CallToolRequest) => { + this.#logToConsole("Calling tool:", params); + const { name, arguments: args } = params; + switch (name) { + case "screens_update_screens": { + const screenInputs = args.screenInputs as ScreenInput[]; + if (!this.#testHarness) { + this.#testHarness = document.querySelector("test-harness"); + if (this.#testHarness) { + this.#testHarness.screens = screens; + this.#testHarness.vfs = this.#vfs; + } + } + + if (!this.#testHarness) { + return { isError: true }; + } + + this.#logToConsole( + "Updating screens:", + screenInputs.map((s) => s.screenId).join(", ") + ); + + const newStates = new Map(this.#testHarness.screenStates); + const updatedScreens = new Set(this.#testHarness.updatedScreens); + for (const screenInput of screenInputs) { + const { screenId } = screenInput; + newStates.set(screenId, screenInput); + updatedScreens.add(screenId); + } + this.#testHarness.screenStates = newStates; + this.#testHarness.updatedScreens = updatedScreens; + + return { + isError: false, + }; + } + case "screens_get_user_events": { + const eventsResponse = await this.eventQueue.get(); + const { events, isError } = eventsResponse; + return { isError, response: { events } }; + } + default: { + this.#logToConsole("Unknown tool", name); + throw new Error(`Unknown tool "${name}"`); + } + } + }, + }; + console = { + log: (...params: unknown[]) => { + this.#logToConsole(...params); + }, + error: (...params: unknown[]) => { + this.#logToConsole("ERROR:", ...params); + }, + }; + prompts: Capabilities["prompts"] = { + get: (id: string, values?: Record) => { + const prompt = promptMap.get(id); + if (!prompt) { + throw new Error(`Prompt with id "${id}" not found`); + } + + if (!values) { + return Promise.resolve(prompt); + } + + const replacer = ( + value: string, + substitutions: Record + ) => { + return value.replace(/{{(.*?)}}/g, (match, key) => { + const parts = key.trim().split("."); + let sub: unknown = substitutions; + for (const part of parts) { + if (typeof sub !== "object" || sub === null) { + return match; + } + sub = (sub as Record)[part]; + } + return sub !== undefined ? String(sub) : match; + }); + }; + + const value = replacer(prompt.value, values); + return Promise.resolve({ ...prompt, value }); + }, + }; +} diff --git a/experiments/screens/src/generate.ts b/experiments/screens/src/generate.ts new file mode 100644 index 00000000000..34c4df8774d --- /dev/null +++ b/experiments/screens/src/generate.ts @@ -0,0 +1,244 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { config } from "dotenv"; +import { join } from "path"; +import { Screen } from "./types"; +import { mkdir, readFile, writeFile } from "fs/promises"; +import { logicPrompt } from "./logic-prompt"; +import { GoogleGenAI } from "@google/genai"; +import { tools } from "./screen-server-tools"; + +type Prompt = { + text: string; +}; + +type Oops = { + error: string; +}; + +type AppImport = { + spec: string; + screens: Screen[]; + prompts: Prompt[]; +}; + +config({ quiet: true }); + +const SCROLLING_WINDOW_SIZE = 6; +const TERMINAL_WIDTH = process.stdout.columns; +const ANSI_GREEN = "\x1B[32m"; +const ANSI_RESET = "\x1B[0m"; +const ANSI_CLEAR_LINE = "\x1B[2K"; +const ANSI_MOVE_UP = `\x1B[${SCROLLING_WINDOW_SIZE + 1}A`; + +const SRC_DIR = join(import.meta.dirname, "../src"); +const APP_DIR = join(SRC_DIR, "apps"); +const OUT_DIR = join(import.meta.dirname, "../out"); + +async function loadMainPrompt(helpers: string): Promise { + const typesPath = join(SRC_DIR, `types.ts`); + try { + const types = await readFile(typesPath, "utf-8"); + return { + text: ` +${logicPrompt} + +Here are all the type defintions: + +\`\`\`typescript +${types} +\`\`\ + +The following tools are available from the McpClient: + +\`\`\`json +${JSON.stringify(tools, null, 2)} +\`\`\` + +Additionally, these helper functions are injected into the module. You can +use them directly: + +\`\`\`js +${helpers} +\`\`\` + +`, + }; + } catch (e) { + return { error: (e as Error).message }; + } +} + +async function loadHelperFunctions(): Promise { + const helpersPath = join(SRC_DIR, `helper-functions.js`); + try { + const text = await readFile(helpersPath, "utf-8"); + return { text }; + } catch (e) { + return { error: (e as Error).message }; + } +} + +async function loadAppPrompt(appName: string): Promise { + const path = join(APP_DIR, `${appName}.ts`); + try { + const { spec, screens, prompts } = (await import(path)) as AppImport; + return { + text: ` +${spec} + +The following screens are defined for this program: + +\`\`\`json +${JSON.stringify(screens, null, 2)} +\`\`\` + + +The following prompts are defined for this program: + +\`\`\`json +${JSON.stringify(prompts, null, 2)} +\`\`\` +`, + }; + } catch (e) { + return { error: (e as Error).message }; + } +} + +const GEMINI_KEY = process.env.VITE_GEMINI_KEY; +if (!GEMINI_KEY) { + console.error( + ` 🔑 Please set VITE_GEMINI_KEY environment variable to run this app` + ); + process.exit(1); +} else { + console.log(` 🔑 VITE_GEMINI_KEY Acquired`); +} + +const APP_NAME = process.argv[2]; +if (!APP_NAME) { + console.warn(` ❓ Usage: npm run generate `); + process.exit(1); +} else { + console.log(` 📱 App: ${APP_NAME}`); +} + +const helpers = await loadHelperFunctions(); +if ("error" in helpers) { + console.error(` 🔩 Unable to Load Helper Functions: ${helpers.error}`); + process.exit(1); +} else { + console.log(` 🔩 Helper Functions Loaded`); +} + +const mainPrompt = await loadMainPrompt(helpers.text); +if ("error" in mainPrompt) { + console.error(` 💾 Unable to Load Main Prompt: ${mainPrompt.error}`); + process.exit(1); +} else { + console.log(` 💬 Main Prompt Loaded`); +} + +const appPrompt = await loadAppPrompt(APP_NAME); +if ("error" in appPrompt) { + console.error(` 💾 Unable to Load App Prompt: ${appPrompt.error}`); + process.exit(1); +} else { + console.log(` 💬 App Prompt Loaded`); +} + +console.log(" 🤖 Generating Code"); +const gemini = new GoogleGenAI({ apiKey: GEMINI_KEY }); + +console.log(" 🧠 Thinking"); +for (let i = 1; i <= SCROLLING_WINDOW_SIZE; i++) { + process.stdout.write( + `${ANSI_GREEN}${i.toString().padStart(3, " ")}${ANSI_RESET}\n` + ); +} +const stream = await gemini.models.generateContentStream({ + model: "gemini-2.5-pro", + contents: { + text: `${appPrompt.text}\n\n${mainPrompt.text}`, + }, + config: { thinkingConfig: { includeThoughts: true, thinkingBudget: -1 } }, +}); +const result: string[] = []; +let currentThought: string = ""; +for await (const chunk of stream) { + const parts = chunk?.candidates?.at(0)?.content?.parts; + if (!parts) continue; + for (const part of parts) { + if (!part.text) { + continue; + } else if (part.thought) { + currentThought = getTitleFromThought(part.text) ?? currentThought; + } else { + appendLines(part.text, result); + } + } + const displayLines = result.slice(-SCROLLING_WINDOW_SIZE); + + while (displayLines.length < SCROLLING_WINDOW_SIZE) { + displayLines.unshift(""); + } + + process.stdout.write( + `${ANSI_MOVE_UP}${ANSI_CLEAR_LINE} 🧠 ${currentThought}\n` + ); + + let startLine = result.length <= 6 ? 1 : result.length - 6; + for (const line of displayLines) { + const lineNumber = startLine.toString().padStart(3, " "); + process.stdout.write( + `${ANSI_CLEAR_LINE}${ANSI_GREEN}${lineNumber} ${line.substring(0, TERMINAL_WIDTH - 4)}${ANSI_RESET}\n` + ); + startLine++; + } +} + +process.stdout.write(`${ANSI_MOVE_UP}${ANSI_CLEAR_LINE}`); + +const destinationFileName = join(OUT_DIR, `${APP_NAME}.js`); + +console.log(` 💾 Saving Output to "out/${APP_NAME}.js"`); + +let code = result.join("\n"); +if (code.endsWith("```")) { + code = code.slice(0, -3); +} + +// Mechanically fix a common problem with +// Gemini adding extra spaces in optional +// property accessors. +code = code.replaceAll(/\?\s*\.\s*\[/g, "?.["); + +try { + await mkdir(OUT_DIR, { recursive: true }); + await writeFile(destinationFileName, `${helpers.text}\n\n${code}`, "utf-8"); +} catch { + console.error(` ❌ failed to save to "${destinationFileName}"`); + process.exit(1); +} + +process.stdout.write(`${ANSI_CLEAR_LINE}`); + +console.log(` ✅ Success`); + +function appendLines(chunk: string, lines: string[]) { + const newLines = chunk.split("\n"); + lines[lines.length - 1] += newLines[0]; + if (newLines.length > 0) { + lines.push(...newLines.slice(1)); + } +} + +function getTitleFromThought(thought: string): string | null { + const match = thought.match(/\*\*(.*?)\*\*/); + return match ? match[1] : null; +} diff --git a/experiments/screens/src/helper-functions.js b/experiments/screens/src/helper-functions.js new file mode 100644 index 00000000000..13d3fc6c48e --- /dev/null +++ b/experiments/screens/src/helper-functions.js @@ -0,0 +1,113 @@ +/** + * Helper function to call a prompt that expects a JSON response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The parsed JSON response. + */ +export async function callJsonPrompt(generate, prompts, promptName, args = {}) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-pro", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + generationConfig: { + responseMimeType: "application/json", + responseSchema: prompt.responseSchema, + }, + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate content.`); + } + const textPart = candidate.content.parts.find((part) => "text" in part); + if (!textPart) { + throw new Error(`No text part in response for ${promptName}.`); + } + return JSON.parse(textPart.text); +} + +/** + * Helper function to call a prompt that expects a text response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The text response. + */ +export async function callTextPrompt(generate, prompts, promptName, args = {}) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-pro", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate content.`); + } + const textPart = candidate.content.parts.find((part) => "text" in part); + if (!textPart) { + throw new Error(`No text part in response for ${promptName}.`); + } + return textPart.text; +} + +/** + * Helper function to call a prompt that expects an image response. + * @param {object} generate - The Gemini generate capability. + * @param {object} prompts - The prompts capability. + * @param {string} promptName - The name of the prompt to call. + * @param {object} [args] - The arguments to pass to the prompt. + * @returns {Promise} The VFS path to the generated image. + */ +export async function callImagePrompt( + generate, + prompts, + promptName, + args = {} +) { + const prompt = await prompts.get(promptName, args); + const response = await generate.generateContent({ + model: "gemini-2.5-flash-image-preview", + contents: [ + { + role: "user", + parts: [ + { + text: prompt.value, + }, + ], + }, + ], + generationConfig: { + responseModalities: ["IMAGE"], + }, + }); + const candidate = response.candidates[0]; + if (!candidate || !candidate.content) { + throw new Error(`Prompt ${promptName} failed to generate an image.`); + } + const filePart = candidate.content.parts.find((part) => "fileData" in part); + if (!filePart) { + throw new Error(`No image part in response for ${promptName}.`); + } + return filePart.fileData.fileUri; +} diff --git a/experiments/screens/src/logic-prompt.ts b/experiments/screens/src/logic-prompt.ts new file mode 100644 index 00000000000..a45b7ce021f --- /dev/null +++ b/experiments/screens/src/logic-prompt.ts @@ -0,0 +1,24 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export const logicPrompt = `To accomplish this task, write a Javascript module with a single anonymous async function as a default export. The module runs in an isolated environment that has the latest ECMAScript features, but no additional bindings. The function you will write is defined as the \`Invoke\` type. + +Any files in this prompt will be provided to the program as "/vfs/in/file_[x]" +files, where x is the index of the file provided. + +When providing files as outputs, output them as \`FilePart\` structures within the +\`LLMContent\`, passing the VFS paths as-is. + +Make sure to write Javascript, not Typescript. Output it directly as Javascript code, with nothing else. This code will be used directly for execution. + +The following Gemini models are available: + +- \`gemini-2.5-pro\` - Enhanced thinking and reasoning, multimodal understanding, advanced coding, and more +- \`gemini-2.5-flash\` - Adaptive thinking, cost efficiency +- \`gemini-2.5-flash-image-preview\` - Precise, conversational image generation + and editing. Importantly, the JSON mode is not enabled for this model. + +`; diff --git a/experiments/screens/src/runner.ts b/experiments/screens/src/runner.ts new file mode 100644 index 00000000000..037129ba062 --- /dev/null +++ b/experiments/screens/src/runner.ts @@ -0,0 +1,20 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/// + +// import adventureGame from "../out/adventure-game"; +import app from "../out/blog-post-writer"; +import { Invoke } from "./types"; +import { CapabilitiesImpl } from "./capabilities"; +import "./ui/test-harness"; + +async function run(app: Invoke) { + const appCapabilities = new CapabilitiesImpl(); + app(appCapabilities); +} + +run(app as unknown as Invoke); diff --git a/experiments/screens/src/screen-server-tools.ts b/experiments/screens/src/screen-server-tools.ts new file mode 100644 index 00000000000..8e29846170b --- /dev/null +++ b/experiments/screens/src/screen-server-tools.ts @@ -0,0 +1,76 @@ +import { FunctionDeclaration } from "./types"; + +export { tools }; + +const updateScreen: FunctionDeclaration = { + name: "screens_update_screens", + description: `Part of the screen server, which manages a set of pre-defined application screens and allows the application to render them and to obtain user inputs from those screens. + +For best results, call \`screens_get_user_events\` prior to \`screens_update_screens\` to capture any events and then act on them to render the right screen. Combined together, \`screens_get_user_events\` and \`screens_update_screens\` form the rendering loop for the application UI. + +This function Updates screens with specified ids. This call does not block on user input. To collect user input from the screen, call \`screens_get_user_events\`. To make updates more efficiens, multiple screens can be updated in a single call.`, + parameters: { + type: "object", + properties: { + screenInputs: { + type: "array", + items: { + type: "object", + properties: { + screenId: { + type: "string", + description: "The id of the screen to update", + }, + inputs: { + type: "object", + description: + "JSON object of the inputs. The shape of the JSON object must conform to the JSON schema specified in the screen definition's `inputSchema` property", + }, + }, + }, + }, + }, + }, +}; + +const getUserEvents: FunctionDeclaration = { + name: "screens_get_user_events", + description: `Part of the screen server, which manages a set of pre-defined application screens and allows the application to render them and to obtain user inputs from those screens. + +For best results, call \`screens_get_user_events\` prior to \`screens_update_screens\` to capture any events and then act on them to render the right screen. Combined together, \`screens_get_user_events\` and \`screens_update_screens\` form the rendering loop for the application UI. + +Gets the list of user events across all screens. Will block until it receives at least one user event. Accumulates and drains the queue of user events when called.`, + parameters: { + type: "object", + }, + response: { + type: "object", + properties: { + events: { + type: "array", + items: { + type: "object", + properties: { + screenId: { + type: "string", + description: + "The id of the screen from which the event originated", + }, + eventId: { + type: "string", + description: "The id of the event that was sent", + }, + output: { + type: "object", + description: + "Structured outputs emitted by event as a JSON object, conforming to the JSON schema specified `outputSchema` property of screen's definition", + }, + }, + required: ["screenId", "eventId"], + }, + }, + }, + }, +}; + +const tools = [updateScreen, getUserEvents]; diff --git a/experiments/screens/src/screenify-prompt.ts b/experiments/screens/src/screenify-prompt.ts new file mode 100644 index 00000000000..64d3aa34a2a --- /dev/null +++ b/experiments/screens/src/screenify-prompt.ts @@ -0,0 +1,30 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +export function createPrompt(intent: string, types: string, example: string) { + return ` +Your job is to come up with a list of screens and prompts for the application based on the application intent specified below. + +Generate output as a TypeScript module that contains three exports: "spec", "screens" and "prompt". See example below. + +The type definitions are as follows: + +\`\`\`ts +${types} +\`\`\` + +## Intent + +${intent} + +## Example + +\`\`\`ts +${example} +\`\`\` + +`; +} diff --git a/experiments/screens/src/screenify.ts b/experiments/screens/src/screenify.ts new file mode 100644 index 00000000000..5d44ddbecc8 --- /dev/null +++ b/experiments/screens/src/screenify.ts @@ -0,0 +1,153 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { GoogleGenAI } from "@google/genai"; +import { config } from "dotenv"; +import { readFile, writeFile } from "fs/promises"; +import { join } from "path"; +import { createPrompt } from "./screenify-prompt"; + +config({ quiet: true }); + +const intent = `Make a blog post writer. It takes a topic, then does some research on it, then writes an outline, then generates an snazzy header graphic based on this outline, and in parallel, writes the blog post based on the outline. Then shows the header graphic and the blog post as a final result.`; +const APP_NAME = "blog-post-writer"; + +const SCROLLING_WINDOW_SIZE = 6; +const TERMINAL_WIDTH = process.stdout.columns; +const ANSI_GREEN = "\x1B[32m"; +const ANSI_RESET = "\x1B[0m"; +const ANSI_CLEAR_LINE = "\x1B[2K"; +const ANSI_MOVE_UP = `\x1B[${SCROLLING_WINDOW_SIZE + 1}A`; + +const SRC_DIR = join(import.meta.dirname, "../src"); +const APP_DIR = join(SRC_DIR, "apps"); + +async function loadTypes(): Promise { + const typesPath = join(SRC_DIR, `types.ts`); + try { + const text = await readFile(typesPath, "utf-8"); + console.log(` 🔩 Types Loaded`); + return text; + } catch (e) { + console.error(` 🔩 Unable to Load Types: ${(e as Error).message}`); + process.exit(1); + } +} + +async function loadExample(): Promise { + const typesPath = join(APP_DIR, `adventure-game.ts`); + try { + const text = await readFile(typesPath, "utf-8"); + console.log(` 🧩 Example Loaded`); + return text; + } catch (e) { + console.error(` 🧩 Unable to Load Example: ${(e as Error).message}`); + process.exit(1); + } +} + +const GEMINI_KEY = process.env.VITE_GEMINI_KEY; +if (!GEMINI_KEY) { + console.error( + ` 🔑 Please set VITE_GEMINI_KEY environment variable to run this app` + ); + process.exit(1); +} else { + console.log(` 🔑 VITE_GEMINI_KEY Acquired`); +} + +const types = await loadTypes(); +const example = await loadExample(); + +console.log(" 🤖 Generating Code"); +const gemini = new GoogleGenAI({ apiKey: GEMINI_KEY }); + +console.log(" 🧠 Thinking"); +for (let i = 1; i <= SCROLLING_WINDOW_SIZE; i++) { + process.stdout.write( + `${ANSI_GREEN}${i.toString().padStart(3, " ")}${ANSI_RESET}\n` + ); +} +const stream = await gemini.models.generateContentStream({ + model: "gemini-2.5-pro", + contents: { + text: createPrompt(intent, types, example), + }, + config: { thinkingConfig: { includeThoughts: true, thinkingBudget: -1 } }, +}); +const result: string[] = []; +let currentThought: string = ""; +for await (const chunk of stream) { + const parts = chunk?.candidates?.at(0)?.content?.parts; + if (!parts) continue; + for (const part of parts) { + if (!part.text) { + continue; + } else if (part.thought) { + currentThought = getTitleFromThought(part.text) ?? currentThought; + } else { + appendLines(part.text, result); + } + } + const displayLines = result.slice(-SCROLLING_WINDOW_SIZE); + + while (displayLines.length < SCROLLING_WINDOW_SIZE) { + displayLines.unshift(""); + } + + process.stdout.write( + `${ANSI_MOVE_UP}${ANSI_CLEAR_LINE} 🧠 ${currentThought}\n` + ); + + let startLine = result.length <= 6 ? 1 : result.length - 6; + for (const line of displayLines) { + const lineNumber = startLine.toString().padStart(3, " "); + process.stdout.write( + `${ANSI_CLEAR_LINE}${ANSI_GREEN}${lineNumber} ${line.substring(0, TERMINAL_WIDTH - 4)}${ANSI_RESET}\n` + ); + startLine++; + } +} + +process.stdout.write(`${ANSI_MOVE_UP}${ANSI_CLEAR_LINE}`); + +const destinationFileName = join(APP_DIR, `${APP_NAME}.ts`); + +console.log(` 💾 Saving Output to "src/apps/${APP_NAME}.ts"`); + +let code = result.join("\n"); +if (code.endsWith("```")) { + code = code.slice(0, -3); +} + +// Mechanically fix a common problem with +// Gemini adding extra spaces in optional +// property accessors. +code = code.replaceAll(/\?\s*\.\s*\[/g, "?.["); + +try { + await writeFile(destinationFileName, code, "utf-8"); +} catch { + console.error(` ❌ failed to save to "${destinationFileName}"`); + process.exit(1); +} + +process.stdout.write(`${ANSI_CLEAR_LINE}`); + +console.log(` ✅ Success`); + +function appendLines(chunk: string, lines: string[]) { + const newLines = chunk.split("\n"); + lines[lines.length - 1] += newLines[0]; + if (newLines.length > 0) { + lines.push(...newLines.slice(1)); + } +} + +function getTitleFromThought(thought: string): string | null { + const match = thought.match(/\*\*(.*?)\*\*/); + return match ? match[1] : null; +} diff --git a/experiments/screens/src/types.ts b/experiments/screens/src/types.ts new file mode 100644 index 00000000000..5802eeda4be --- /dev/null +++ b/experiments/screens/src/types.ts @@ -0,0 +1,419 @@ +export type Schema = { + type: "string" | "number" | "integer" | "boolean" | "object" | "array"; + format?: string; + description?: string; + nullable?: boolean; + enum?: string[]; + maxItems?: string | number; + minItems?: string | number; + properties?: Record; + anyOf?: Schema[]; + required?: string[]; + items?: Schema; +}; + +/** + * Represents data that was validated to conform to a JSON schema that is + * appropriate for the context. + */ +export type SchemaValidated = + | string + | number + | boolean + | null + | Array + | { + [K: string]: SchemaValidated; + }; + +export type CallToolRequest = { + name: string; + arguments: Record; +}; + +export type CallToolResponse = { + response?: SchemaValidated; + isError: boolean; +}; + +export type McpClient = { + callTool(params: CallToolRequest): Promise; +}; + +export type Console = { + /** + * Call this method to report errors. + * @param params -- useful information about the error, usually strings + */ + error(...params: unknown[]): void; + /** + * Call this method to log progress. + * @param params -- useful information to log, usually strings + */ + log(...params: unknown[]): void; +}; + +export type Capabilities = { + generate: Gemini; + mcp: McpClient; + console: Console; + /** + * The prompt capabilities. + */ + prompts: { + /** + * Gets a prompt by id. + * @param id The id of the prompt. + * @param values A property bag for substituting placeholders in the prompt. + * @returns The prompt with the placeholders substituted. + */ + get: ( + id: string, + values?: Record + ) => Promise; + }; +}; + +export type Invoke = (capabilities: Capabilities) => Promise; + +export type Screen = { + screenId: string; + description: string; + inputSchema: Schema; + events: EventDescriptor[]; +}; + +export type EventDescriptor = { + eventId: string; + description: string; + /** + * The schema for the data that is dispatched along with the event. IF not + * present, there's no additional data supplied for this event. + */ + outputSchema?: Schema; +}; + +export type PromptArgument = { + /** + * The name of the argument. + */ + name: string; + /** + * Descriptiong of the argument: how will it be used in the prompt. + */ + description: string; + /** + * Whether or not the argument is required + */ + required: boolean; +}; + +export type Prompt = { + name: string; + description: string; + /** + * Whether prompt's generated output will be text, JSON, or image. + */ + format: "text" | "json" | "image"; + /** + * The arguments for the prompt that will populate prompt placeholders. + * For example, if the prompt has an {{origin}} placeholder in it, + * the expected value of arguments will be: + * + * ```json + * [ + * { + * "name": "origin", + * "description": "The origin point in the map", + * "required": true + * } + * ] + * ``` + */ + arguments?: PromptArgument[]; + /** + * The JSON schema that accompanies the prompt. Is only provided when + * the format = "json". Supply it as the `responseSchema` to the Gemini API. + */ + responseSchema?: Schema; + value: string; +}; + +export type ScreenInput = { + screenId: string; + inputs: SchemaValidated; +}; + +export type GetUserEventsResponse = { + events: UserEvent[]; + isError: boolean; +}; + +export type RenderScreenResponse = { + isError: boolean; +}; + +export type UserEvent = { + screenId: string; + eventId: string; + output?: SchemaValidated; +}; + +/** + * Access to Gemini API + */ +export type Gemini = { + generateContent(args: GeminiInputs): Promise; +}; + +export type HarmBlockThreshold = + // Content with NEGLIGIBLE will be allowed. + | "BLOCK_LOW_AND_ABOVE" + // Content with NEGLIGIBLE and LOW will be allowed. + | "BLOCK_MEDIUM_AND_ABOVE" + // Content with NEGLIGIBLE, LOW, and MEDIUM will be allowed. + | "BLOCK_ONLY_HIGH" + // All content will be allowed. + | "BLOCK_NONE" + // Turn off the safety filter. + | "OFF"; + +export type HarmCategory = + // Gemini - Harassment content + | "HARM_CATEGORY_HARASSMENT" + // Gemini - Hate speech and content. + | "HARM_CATEGORY_HATE_SPEECH" + // Gemini - Sexually explicit content. + | "HARM_CATEGORY_SEXUALLY_EXPLICIT" + // Gemini - Dangerous content. + | "HARM_CATEGORY_DANGEROUS_CONTENT" + // Gemini - Content that may be used to harm civic integrity. + | "HARM_CATEGORY_CIVIC_INTEGRITY"; + +export type Modality = "TEXT" | "IMAGE" | "AUDIO"; + +/** + * Allows choosing between various modes of the generated output. + * - To choose JSON mode (JSON output), set `responseMimeType` to + * `application/json` and provide `responseSchema`. + * - To choose text output mode, do not provide GenerationConfig at all + * - TO choese image output mode, set `responseModalities` to `["IMAGE"]` and + * do NOT set `responseMimeType`. + */ +export type GenerationConfig = { + responseMimeType?: "text/plain" | "application/json" | "text/x.enum"; + responseSchema?: Schema; + responseModalities?: Modality[]; +}; + +export type SafetySetting = { + category: HarmCategory; + threshold: HarmBlockThreshold; +}; + +export type FunctionCallPart = { + functionCall: { + name: string; + args: object; + }; +}; + +export type FunctionResponsePart = { + functionResponse: { + name: string; + response: object; + }; +}; + +export type TextPart = { + text: string; +}; + +export type DataStoreHandle = string; + +export type FileDataPart = { + fileData: { + /** + * Can be one of these three: + * - a URL pointing to a YT video + * - a URL pointing at a resource saved with File API. + * - a VFS path in the format of "/vfs/out/[guid]" + */ + fileUri: string; + mimeType: string; + resourceKey?: string; + }; +}; + +export type ExecutableCodePart = { + executableCode: { + language: "LANGUAGE_UNSPECIFIED" | "PYTHON"; + code: string; + }; +}; + +export type CodeExecutionResultOutcome = + // Unspecified status. This value should not be used. + | "OUTCOME_UNSPECIFIED" + // Code execution completed successfully. + | "OUTCOME_OK" + // Code execution finished but with a failure. stderr should contain the reason. + | "OUTCOME_FAILED" + // Code execution ran for too long, and was cancelled. There may or may not be a partial output present. + | "OUTCOME_DEADLINE_EXCEEDED"; + +export type CodeExecutionResultPart = { + codeExecutionResult: { + outcome: CodeExecutionResultOutcome; + output: string; + }; +}; + +export type DataPart = + | InlineDataPart + | FileDataPart + | ExecutableCodePart + | CodeExecutionResultPart + | FunctionCallPart + | FunctionResponsePart + | TextPart; + +export type LLMContent = { + role?: string; + parts: DataPart[]; +}; + +/** + * Represents inline data, encoded as a base64 string. Use only for inputs. + * Outputs are always provided as FileData with VFS path. + */ +export type InlineDataPart = { + inlineData: { + mimeType: string; + data: string; + title?: string; + }; +}; + +export type GeminiInputs = { + model?: string; + contents: LLMContent[]; + tools?: Tool[]; + toolConfig?: ToolConfig; + systemInstruction?: LLMContent; + safetySettings?: SafetySetting[]; + generationConfig?: GenerationConfig; +}; + +export type Tool = { + functionDeclarations?: FunctionDeclaration[]; + // eslint-disable-next-line @typescript-eslint/no-empty-object-type + googleSearch?: {}; + codeExecution?: CodeExecution; +}; + +export type ToolConfig = { + functionCallingConfig?: FunctionCallingConfig; +}; + +export type FunctionCallingConfig = { + mode?: "MODE_UNSPECIFIED" | "AUTO" | "ANY" | "NONE"; + allowedFunctionNames?: string[]; +}; + +export type FunctionDeclaration = { + name: string; + description: string; + parameters?: Schema; + response?: Schema; +}; + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export type CodeExecution = { + // Type contains no fields. +}; + +export type FinishReason = + // Natural stop point of the model or provided stop sequence. + | "STOP" + // The maximum number of tokens as specified in the request was reached. + | "MAX_TOKENS" + // The response candidate content was flagged for safety reasons. + | "SAFETY" + // The response candidate content was flagged for image safety reasons. + | "IMAGE_SAFETY" + // The response candidate content was flagged for recitation reasons. + | "RECITATION" + // The response candidate content was flagged for using an unsupported language. + | "LANGUAGE" + // Unknown reason. + | "OTHER" + // Token generation stopped because the content contains forbidden terms. + | "BLOCKLIST" + // Token generation stopped for potentially containing prohibited content. + | "PROHIBITED_CONTENT" + // Token generation stopped because the content potentially contains Sensitive Personally Identifiable Information (SPII). + | "SPII" + // The function call generated by the model is invalid. + | "MALFORMED_FUNCTION_CALL"; + +export type GroundingMetadata = { + groundingChunks: { + web: { + uri: string; + title: string; + }; + }[]; + groundingSupports: { + groundingChunkIndices: number[]; + confidenceScores: number[]; + segment: { + partIndex: number; + startIndex: number; + endIndex: number; + text: string; + }; + }; + webSearchQueries: string[]; + searchEntryPoint: { + renderedContent: string; + /** + * Base64 encoded JSON representing array of tuple. + * A base64-encoded string. + */ + sdkBlob: string; + }; + retrievalMetadata: { + googleSearchDynamicRetrievalScore: number; + }; +}; + +export type Candidate = { + /** + * The LLM output. + * IMPORTANT: Unlike the standard Gemini API, any media will be provided as + * the `FileDataPart` with the `fileUri` populated with the VFS file path. + * The VFS is the virtual file system that allows efficiently passing large + * media files within the application. The VFS paths are opaque identifiers + * for media files and can be provided as both inputs and outputs. The VFS + * files always start with "/vfs/". + * Note, that the `FileDataPart` might be mixed with `TextPart`s. When + * looking for it, first filter out the text parts and then get the first + * `FileDataPart`. + */ + content?: LLMContent; + finishReason?: FinishReason; + safetyRatings?: SafetySetting[]; + tokenOutput?: number; + groundingMetadata?: GroundingMetadata; +}; + +export type GeminiOutputs = { + candidates: Candidate[]; +}; + +export type AppImport = { + spec: string; + screens: Screen[]; + prompts: Prompt[]; +}; diff --git a/experiments/screens/src/ui/console-view.ts b/experiments/screens/src/ui/console-view.ts new file mode 100644 index 00000000000..fbdd028bcf0 --- /dev/null +++ b/experiments/screens/src/ui/console-view.ts @@ -0,0 +1,55 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { LitElement, html, css, PropertyValues } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +@customElement("console-view") +export class ConsoleView extends LitElement { + @property({ type: Array }) + log: unknown[][] = []; + + static styles = css` + :host { + border-top: 1px solid #ccc; + padding-top: 10px; + overflow-y: scroll; + height: 200px; + } + h1 { + font-size: 1.2em; + margin-top: 0; + } + .log-entry { + font-family: monospace; + padding: 5px; + border-bottom: 1px solid #eee; + } + `; + + updated(changedProperties: PropertyValues) { + super.updated(changedProperties); + if (changedProperties.has("log")) { + this.scrollTop = this.scrollHeight; + } + } + + render() { + return html` +

Console

+ ${this.log.map( + (entry) => + html`
+ ${entry + .map((item) => + typeof item === "string" ? item : JSON.stringify(item) + ) + .join(" ")} +
` + )} + `; + } +} diff --git a/experiments/screens/src/ui/screen-renderer.ts b/experiments/screens/src/ui/screen-renderer.ts new file mode 100644 index 00000000000..cd0cdbbc662 --- /dev/null +++ b/experiments/screens/src/ui/screen-renderer.ts @@ -0,0 +1,128 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { LitElement, html, css } from "lit"; +import { customElement, property } from "lit/decorators.js"; +import { Screen, SchemaValidated } from "../types"; + +@customElement("screen-renderer") +export class ScreenRenderer extends LitElement { + @property({ type: Object }) + screen?: Screen; + + @property({ type: Object }) + inputs: SchemaValidated = {}; + + @property({ type: Object }) + vfs = new Map(); + + static styles = css` + .screen { + padding: 20px; + } + .inputs, + .events { + margin-bottom: 20px; + } + label { + display: block; + margin-bottom: 10px; + } + textarea { + width: 100%; + } + img { + max-width: 100%; + } + `; + + #onEvent(eventId: string, output?: Record) { + this.dispatchEvent( + new CustomEvent("user-event", { + detail: { + screenId: this.screen?.screenId, + eventId, + output, + }, + bubbles: true, + composed: true, + }) + ); + } + + render() { + if (!this.screen) { + return html`

No screen selected

`; + } + + return html` +
+
+

${this.screen.screenId}

+ ${Object.entries(this.screen.inputSchema.properties ?? {}).map( + ([key, schema]) => { + const value = (this.inputs as Record)[ + key + ]; + const isVfsPath = + typeof value === "string" && value.startsWith("/vfs/out/"); + const vfsUrl = isVfsPath ? this.vfs.get(value) : null; + return html` +
+ + ${vfsUrl + ? html`` + : html`

${String(value)}

`} +
+ `; + } + )} +
+
+ ${this.screen.events.map( + (event) => html` +
{ + e.preventDefault(); + if (!event.outputSchema) return; + const formData = new FormData(e.target as HTMLFormElement); + const output: Record = {}; + for (const [key] of Object.entries( + event.outputSchema.properties ?? {} + )) { + output[key] = formData.get(key) as string; + } + this.#onEvent(event.eventId, output); + }} + > +
+ ${event.description} + ${Object.entries(event.outputSchema?.properties ?? {}).map( + ([key]) => html` + + ` + )} + +
+ + ` + )} +
+
+ `; + } +} diff --git a/experiments/screens/src/ui/test-harness.ts b/experiments/screens/src/ui/test-harness.ts new file mode 100644 index 00000000000..d3bdecd9573 --- /dev/null +++ b/experiments/screens/src/ui/test-harness.ts @@ -0,0 +1,168 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { LitElement, html, css } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import { Screen, ScreenInput } from "../types"; +import "./screen-renderer"; +import "./console-view"; + +@customElement("test-harness") +export class TestHarness extends LitElement { + @property({ type: Array }) + screens: Screen[] = []; + + @property({ type: Object }) + screenStates = new Map(); + + @property({ type: Array }) + log: unknown[][] = []; + + @property({ type: Object }) + vfs = new Map(); + + @state() + activeScreen: string | null = null; + + @state() + updatedScreens = new Set(); + + static styles = css` + :host { + display: flex; + flex-direction: column; + height: 100vh; + font-family: sans-serif; + } + + .header { + display: flex; + align-items: center; + border-bottom: 1px solid #ccc; + } + + .tabs { + display: flex; + border-bottom: none; + } + + .tab { + padding: 10px; + cursor: pointer; + border: 1px solid #ccc; + border-bottom: none; + margin-right: 5px; + position: relative; + } + + .tab.active { + background-color: #eee; + } + + .tab.updated::after { + content: ""; + position: absolute; + top: 5px; + right: 5px; + width: 10px; + height: 10px; + background-color: red; + border-radius: 50%; + } + + .spinner { + width: 16px; + height: 16px; + border: 2px solid #eee; + border-top-color: #333; + border-radius: 50%; + margin-left: 10px; + display: none; + animation: spin 1s linear infinite; + } + + .spinner.active { + display: block; + } + + @keyframes spin { + to { + transform: rotate(360deg); + } + } + + .content { + flex: 1; + overflow-y: auto; + height: 60%; + } + + console-view { + height: 40%; + } + `; + + willUpdate(changedProperties: Map) { + if (changedProperties.has("screens") && this.screens.length > 0) { + this.activeScreen = this.screens[0].screenId; + } + } + + #onTabClick(e: Event) { + const target = e.target as HTMLElement; + const screenId = target.dataset.screenId; + if (screenId) { + this.activeScreen = screenId; + } + } + + #onUserEvent() { + this.updatedScreens = new Set(); + } + + render() { + const activeScreenState = this.activeScreen + ? this.screenStates.get(this.activeScreen) + : undefined; + + return html` +
+
+ ${this.screens.map( + (screen) => html` + + ` + )} +
+
+
+
+ ${activeScreenState + ? html` s.screenId === this.activeScreen + )} + .inputs=${activeScreenState.inputs} + .vfs=${this.vfs} + >` + : html`

No active screen

`} +
+ + `; + } +} diff --git a/experiments/screens/test/adventure-game.test.ts b/experiments/screens/test/adventure-game.test.ts new file mode 100644 index 00000000000..fd3750955ab --- /dev/null +++ b/experiments/screens/test/adventure-game.test.ts @@ -0,0 +1,342 @@ +import { test } from "node:test"; +import assert from "node:assert"; +import { TestHarness, findLastScreen } from "./test-harness.js"; +import adventureGame from "../out/adventure-game.js"; +import { Invoke, Prompt, SchemaValidated } from "../src/types.js"; +import { prompts } from "../src/apps/adventure-game.js"; + +const promptMap = new Map( + prompts.map((prompt) => [prompt.id, prompt]) +); + +export const replacer = ( + value: string, + substitutions: Record +): string => { + return value.replace(/{{(.*?)}}/g, (match, key) => { + const parts = key.trim().split("."); + let current: SchemaValidated | undefined = substitutions; + for (const part of parts) { + if ( + current && + typeof current === "object" && + !Array.isArray(current) && + part in current + ) { + current = current[part]; + } else { + return match; + } + } + return String(current); + }); +}; + +test("adventure-game", async (t) => { + const harness = new TestHarness(adventureGame as unknown as Invoke); + try { + // Canned responses for character generation + harness.cannedResponse( + [ + { + role: "user", + parts: [ + { + text: promptMap.get("generate-inspiration")?.value, + }, + ], + }, + ], + { + candidates: [ + { + content: { + parts: [ + { + text: "A quest to find a lost city of gold.", + }, + ], + }, + }, + ], + } + ); + harness.cannedResponse( + [ + { + role: "user", + parts: [ + { + text: replacer( + promptMap.get("generate-plot-and-character")?.value || "", + { + inspiration: "A quest to find a lost city of gold.", + } + ), + }, + ], + }, + ], + { + candidates: [ + { + content: { + parts: [ + { + text: JSON.stringify({ + plot: "The lost city of El Dorado is real...", + characterBio: "A daring explorer.", + characterImagePrompt: "An explorer.", + }), + }, + ], + }, + }, + ], + } + ); + harness.cannedResponse( + [ + { + role: "user", + parts: [{ text: "An explorer." }], + }, + ], + { + candidates: [ + { + content: { + parts: [ + { + fileData: { + fileUri: "path/to/explorer.png", + mimeType: "image/png", + }, + }, + ], + }, + }, + ], + } + ); + + // Canned responses for the first turn + harness.cannedResponse( + [ + { + role: "user", + parts: [ + { + text: replacer(promptMap.get("generate-next-turn")?.value || "", { + plot: "The lost city of El Dorado is real...", + character: { + bio: "A daring explorer.", + }, + history: "The adventure is just beginning.", + }), + }, + ], + }, + ], + { + candidates: [ + { + content: { + parts: [ + { + text: JSON.stringify({ + sceneText: "You stand at the edge of a dense jungle.", + sceneImagePrompt: "A dense jungle.", + choices: ["Go left", "Go right", "Go straight", "Go back"], + }), + }, + ], + }, + }, + ], + } + ); + harness.cannedResponse( + [ + { + role: "user", + parts: [{ text: "A dense jungle." }], + }, + ], + { + candidates: [ + { + content: { + parts: [ + { + fileData: { + fileUri: "path/to/jungle.png", + mimeType: "image/png", + }, + }, + ], + }, + }, + ], + } + ); + + // Canned responses for the second turn (leading to finale) + harness.cannedResponse( + [ + { + role: "user", + parts: [ + { + text: replacer( + promptMap.get("update-plot-based-on-choice")?.value || "", + { + plot: "The lost city of El Dorado is real...", + currentScene: { + text: "You stand at the edge of a dense jungle.", + }, + choice: "Go right", + } + ), + }, + ], + }, + ], + { + candidates: [ + { + content: { + parts: [ + { + text: JSON.stringify({ + updatedPlot: + "You follow a hidden path to the right and discover the city!", + boonSecured: true, + }), + }, + ], + }, + }, + ], + } + ); + harness.cannedResponse( + [ + { + role: "user", + parts: [ + { + text: replacer(promptMap.get("generate-finale")?.value || "", { + plot: "You follow a hidden path to the right and discover the city!", + character: { + bio: "A daring explorer.", + }, + }), + }, + ], + }, + ], + { + candidates: [ + { + content: { + parts: [ + { + text: JSON.stringify({ + finaleText: "You have found El Dorado!", + finaleImagePrompt: "The city of gold.", + }), + }, + ], + }, + }, + ], + } + ); + harness.cannedResponse( + [ + { + role: "user", + parts: [{ text: "The city of gold." }], + }, + ], + { + candidates: [ + { + content: { + parts: [ + { + fileData: { + fileUri: "path/to/eldorado.png", + mimeType: "image/png", + }, + }, + ], + }, + }, + ], + } + ); + + await t.test("start game and generate inspiration", async () => { + await harness.next([ + { screenId: "start_game", eventId: "generate_inspiration" }, + ]); + + const startGame = findLastScreen(harness.history, "start_game"); + assert(startGame, "start_game screen not found"); + assert.strictEqual( + (startGame.inputs as { generatedInspiration: string }) + .generatedInspiration, + "A quest to find a lost city of gold." + ); + }); + + await t.test("start and generate character", async () => { + await harness.next([ + { + screenId: "start_game", + eventId: "start", + output: { inspiration: "A quest to find a lost city of gold." }, + }, + ]); + + const chooseCharacter = findLastScreen( + harness.history, + "choose_character" + ); + assert(chooseCharacter, "choose_character screen not found"); + const inputs = chooseCharacter.inputs as { + bio: string; + picture: string; + }; + assert.strictEqual(inputs.bio, "A daring explorer."); + assert.strictEqual(inputs.picture, "path/to/explorer.png"); + }); + + await t.test("play through a turn", async () => { + await harness.next([{ screenId: "choose_character", eventId: "choose" }]); + + const scene = findLastScreen(harness.history, "scene"); + assert(scene, "scene screen not found"); + const inputs = scene.inputs as { text: string }; + assert.strictEqual( + inputs.text, + "You stand at the edge of a dense jungle." + ); + }); + + await t.test("reach the finale", async () => { + await harness.next([ + { screenId: "scene", eventId: "choose", output: { choice: 2 } }, + ]); + + const finale = findLastScreen(harness.history, "finale"); + assert(finale, "finale screen not found"); + const inputs = finale.inputs as { text: string }; + assert.strictEqual(inputs.text, "You have found El Dorado!"); + }); + } finally { + harness.destroy(); + } +}); diff --git a/experiments/screens/test/mock-capabilities.ts b/experiments/screens/test/mock-capabilities.ts new file mode 100644 index 00000000000..bf8e987a68a --- /dev/null +++ b/experiments/screens/test/mock-capabilities.ts @@ -0,0 +1,147 @@ +import { + Capabilities, + ScreenServer, + Gemini, + ScreenInput, + GetUserEventsResponse, + GeminiInputs, + GeminiOutputs, + LLMContent, + UserEvent, + McpClient, + Prompt, +} from "../src/types.js"; +import { prompts } from "../src/apps/adventure-game.js"; +import { replacer } from "./adventure-game.test.js"; + +const promptMap = new Map( + prompts.map((prompt) => [prompt.id, prompt]) +); + +export class MockCapabilities implements Capabilities { + screens: ScreenServer; + generate: Gemini; + console: Console; + mcp: McpClient; + prompts: Capabilities["prompts"]; + + private screenHistory: ScreenInput[][] = []; + private eventQueue: UserEvent[][] = []; + private cannedResponses: Record = {}; + private pendingResolve: ((value: GetUserEventsResponse) => void) | null = + null; + private pendingReject: ((reason?: Error) => void) | null = null; + private timeoutId: NodeJS.Timeout | null = null; + + constructor() { + this.screens = { + updateScreens: async (screens: ScreenInput[]) => { + this.screenHistory.push(screens); + return { isError: false }; + }, + getUserEvents: async (): Promise => { + return new Promise((resolve, reject) => { + this.pendingResolve = resolve; + this.pendingReject = reject; + const checkQueue = () => { + if (this.eventQueue.length > 0) { + const events = this.eventQueue.shift() || []; + this.pendingResolve = null; + this.pendingReject = null; + resolve({ events, isError: false }); + } else { + this.timeoutId = setTimeout(checkQueue, 10); + } + }; + checkQueue(); + }); + }, + }; + + this.generate = { + generateContent: async ( + request: GeminiInputs + ): Promise => { + const key = JSON.stringify(request.contents); + if (this.cannedResponses[key]) { + const response = this.cannedResponses[key]; + // Simulate the VFS processing of inlineData. + if (response.candidates) { + response.candidates = response.candidates.map((candidate) => { + if (candidate.content && candidate.content.parts) { + candidate.content.parts = candidate.content.parts.map( + (part) => { + if ("inlineData" in part) { + return { + fileData: { + mimeType: part.inlineData.mimeType, + fileUri: `/vfs/out/mock-${Math.random() + .toString(36) + .substring(2)}`, + }, + }; + } + return part; + } + ); + } + return candidate; + }); + } + return response; + } + throw new Error(`No canned response for request: ${key}`); + }, + }; + + this.prompts = { + get: async (id, values) => { + const prompt = promptMap.get(id); + if (!prompt) { + throw new Error(`Prompt with id "${id}" not found`); + } + + if (!values) { + return prompt; + } + + const value = replacer(prompt.value, values); + return { ...prompt, value }; + }, + }; + + this.console = console; + this.mcp = { + callTool: async () => { + throw new Error("not implemented"); + }, + }; + } + + // Test methods + injectEvents(events: UserEvent[]) { + this.eventQueue.push(events); + if (this.pendingResolve) { + if (this.timeoutId) clearTimeout(this.timeoutId); + const events = this.eventQueue.shift() || []; + this.pendingResolve({ events, isError: false }); + this.pendingResolve = null; + this.pendingReject = null; + } + } + + cannedResponse(request: LLMContent[], response: GeminiOutputs) { + this.cannedResponses[JSON.stringify(request)] = response; + } + + getScreenHistory() { + return this.screenHistory; + } + + destroy() { + if (this.timeoutId) clearTimeout(this.timeoutId); + if (this.pendingReject) { + this.pendingReject(new Error("Test finished")); + } + } +} diff --git a/experiments/screens/test/test-harness.ts b/experiments/screens/test/test-harness.ts new file mode 100644 index 00000000000..8a021ccb1df --- /dev/null +++ b/experiments/screens/test/test-harness.ts @@ -0,0 +1,53 @@ +import { + ScreenInput, + UserEvent, + LLMContent, + GeminiOutputs, + Invoke, +} from "../src/types.js"; +import { MockCapabilities } from "./mock-capabilities.js"; + +export function findLastScreen( + history: ScreenInput[][], + screenId: string +): ScreenInput | null { + for (let i = history.length - 1; i >= 0; i--) { + const update = history[i]; + const screen = update.find((item) => item.screenId === screenId); + if (screen) { + return screen; + } + } + return null; +} + +export class TestHarness { + #capabilities: MockCapabilities; + #gamePromise: Promise; + + constructor(app: Invoke) { + this.#capabilities = new MockCapabilities(); + this.#gamePromise = app(this.#capabilities); + this.#gamePromise.catch(() => { + // Do nothing. This is expected when the test finishes. + }); + } + + cannedResponse(request: LLMContent[], response: GeminiOutputs) { + this.#capabilities.cannedResponse(request, response); + } + + async next(events: UserEvent[]) { + this.#capabilities.injectEvents(events); + // Give the game loop a moment to process the event. + await new Promise((resolve) => setTimeout(resolve, 20)); + } + + get history() { + return this.#capabilities.getScreenHistory(); + } + + destroy() { + this.#capabilities.destroy(); + } +} diff --git a/experiments/screens/tsconfig.json b/experiments/screens/tsconfig.json new file mode 100644 index 00000000000..558af8e6897 --- /dev/null +++ b/experiments/screens/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "node", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "allowJs": true, + "checkJs": false, + "resolveJsonModule": true, + "isolatedModules": true, + "lib": ["ESNext", "DOM"], + "experimentalDecorators": true, + "useDefineForClassFields": false + }, + "include": ["src/**/*.ts"] +} diff --git a/package-lock.json b/package-lock.json index 6470282323b..3a9f8912308 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,22994 +11,7593 @@ "workspaces": [ "./core/*", "./packages/*", - "./packages/node-proxy-server/functions" + "./experiments/*" ], - "dependencies": { - "json-schema": "^0.4.0", - "litegraph.js": "^0.7.18", - "prettier": "^3.3.2" - }, "devDependencies": { - "@changesets/cli": "^2.27.8", - "@rollup/plugin-node-resolve": "^15.3.0", - "@rollup/plugin-terser": "^0.4.4", "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", + "@typescript-eslint/eslint-plugin": "^8.43.0", + "@typescript-eslint/parser": "^8.34.1", + "ava": "6.4.1", "eslint": "^8.57.1", - "eslint-plugin-expect-type": "^0.4.3", - "npm-ci": "^0.0.2", - "rimraf": "^6.0.1", - "rollup": "^4.22.4", - "rollup-plugin-dts": "^6.1.1", - "syncpack": "^13.0.0", - "typescript": "^5.6.2", - "wireit": "^0.14.9" - }, - "optionalDependencies": { - "@rollup/rollup-darwin-arm64": "^4.22.2", - "@rollup/rollup-linux-x64-gnu": "^4.21.2" + "eslint-plugin-expect-type": "^0.6.2", + "prettier": "^3.6.2", + "syncpack": "^13.0.3", + "typescript": "^5.8.3", + "wireit": "^0.15.0-pre.2" } }, "core/tsconfig": { "name": "@google-labs/tsconfig", - "version": "0.0.1" - }, - "node_modules/@11ty/dependency-tree": { - "version": "2.0.1", - "dev": true, - "license": "MIT" + "version": "0.0.2" }, - "node_modules/@11ty/eleventy": { - "version": "2.0.1", - "dev": true, - "license": "MIT", + "experiments/agent": { + "name": "vfs", + "version": "1.0.0", + "license": "Apache-2.0", "dependencies": { - "@11ty/dependency-tree": "^2.0.1", - "@11ty/eleventy-dev-server": "^1.0.4", - "@11ty/eleventy-utils": "^1.0.1", - "@11ty/lodash-custom": "^4.17.21", - "@iarna/toml": "^2.2.5", - "@sindresorhus/slugify": "^1.1.2", - "bcp-47-normalize": "^1.1.1", - "chokidar": "^3.5.3", - "cross-spawn": "^7.0.3", - "debug": "^4.3.4", - "dependency-graph": "^0.11.0", - "ejs": "^3.1.9", - "fast-glob": "^3.2.12", - "graceful-fs": "^4.2.11", - "gray-matter": "^4.0.3", - "hamljs": "^0.6.2", - "handlebars": "^4.7.7", - "is-glob": "^4.0.3", - "iso-639-1": "^2.1.15", - "kleur": "^4.1.5", - "liquidjs": "^10.7.0", - "luxon": "^3.3.0", - "markdown-it": "^13.0.1", - "micromatch": "^4.0.5", - "minimist": "^1.2.8", - "moo": "^0.5.2", - "multimatch": "^5.0.0", - "mustache": "^4.2.0", - "normalize-path": "^3.0.0", - "nunjucks": "^3.2.3", - "path-to-regexp": "^6.2.1", - "please-upgrade-node": "^3.2.0", - "posthtml": "^0.16.6", - "posthtml-urls": "^1.0.0", - "pug": "^3.0.2", - "recursive-copy": "^2.0.14", - "semver": "^7.3.8", - "slugify": "^1.6.6" + "@google/genai": "^1.27.0", + "dotenv": "^17.2.3", + "mime": "^4.1.0", + "zod": "^3.24.1", + "zod-to-json-schema": "^3.24.6" }, - "bin": { - "eleventy": "cmd.js" + "devDependencies": { + "tsx": "^4.20.6" + } + }, + "experiments/logic": { + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@google/genai": "^1.27.0", + "dotenv": "^17.2.3" }, - "engines": { - "node": ">=14" + "devDependencies": { + "tsx": "^4.20.6", + "wireit": "^0.15.0-pre.2" + } + }, + "experiments/screens": { + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@google/genai": "^1.27.0", + "dotenv": "^17.2.3", + "lit": "^3.3.1", + "vite": "^7.2.6" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" + "devDependencies": { + "tsx": "^4.20.6" } }, - "node_modules/@11ty/eleventy-dev-server": { - "version": "1.0.4", + "node_modules/@acemir/cssom": { + "version": "0.9.28", + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.28.tgz", + "integrity": "sha512-LuS6IVEivI75vKN8S04qRD+YySP0RmU/cV8UNukhQZvprxF+76Z43TNo/a08eCodaGhT1Us8etqS1ZRY9/Or0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@asamuzakjp/css-color": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.0.tgz", + "integrity": "sha512-9xiBAtLn4aNsa4mDnpovJvBn72tNEIACyvlqaNJ+ADemR+yeMJWnBudOi2qGDviJa7SwcDOU/TRh5dnET7qk0w==", "dev": true, "license": "MIT", "dependencies": { - "@11ty/eleventy-utils": "^1.0.1", - "chokidar": "^3.5.3", - "debug": "^4.3.4", - "dev-ip": "^1.0.1", - "finalhandler": "^1.2.0", - "mime": "^3.0.0", - "minimist": "^1.2.8", - "morphdom": "^2.7.0", - "please-upgrade-node": "^3.2.0", - "ssri": "^8.0.1", - "ws": "^8.13.0" - }, - "bin": { - "eleventy-dev-server": "cmd.js" - }, + "@csstools/css-calc": "^2.1.4", + "@csstools/css-color-parser": "^3.1.0", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "lru-cache": "^11.2.2" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "dev": true, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" + "node": "20 || >=22" } }, - "node_modules/@11ty/eleventy-fetch": { - "version": "4.0.1", + "node_modules/@asamuzakjp/dom-selector": { + "version": "6.7.6", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.6.tgz", + "integrity": "sha512-hBaJER6A9MpdG3WgdlOolHmbOYvSk46y7IQN/1+iqiCuUu6iWdQrs9DGKF8ocqsEqWujWf/V7b7vaDgiUmIvUg==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.4", - "flat-cache": "^3.0.4", - "node-fetch": "^2.6.7", - "p-queue": "^6.6.2" - }, + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.1.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.2.4" + } + }, + "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "dev": true, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" + "node": "20 || >=22" } }, - "node_modules/@11ty/eleventy-plugin-rss": { - "version": "1.2.0", + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ava/typescript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@ava/typescript/-/typescript-6.0.0.tgz", + "integrity": "sha512-+8oDYc4J5cCaWZh1VUbyc+cegGplJO9FqHpqR4LVAVx8fRLVRaYlC4yyA6cqHJ1vWP23Ff/ECS5U68Zz6OLZlg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "debug": "^4.3.4", - "posthtml": "^0.16.6", - "posthtml-urls": "1.0.0" + "escape-string-regexp": "^5.0.0", + "execa": "^9.6.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" + "engines": { + "node": "^20.8 || ^22 || >=24" } }, - "node_modules/@11ty/eleventy-plugin-syntaxhighlight": { + "node_modules/@ava/typescript/node_modules/escape-string-regexp": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true, "license": "MIT", - "dependencies": { - "prismjs": "^1.29.0" + "optional": true, + "peer": true, + "engines": { + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@11ty/eleventy-plugin-vite": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@11ty/eleventy-plugin-vite/-/eleventy-plugin-vite-4.0.0.tgz", - "integrity": "sha512-WYFtQgo965lJCzs8u0930nmbcf8QGrLNTc2EbLNuDSj1Jhy1mIj/sHqxjLgANXKL0Wr2N1ANF3gfdG6Tkeyotg==", + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", "dependencies": { - "lodash.merge": "^4.6.2", - "vite": "^4.0.4" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { - "node": ">=14.18.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" + "node": ">=6.9.0" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "android" - ], + "node_modules/@babel/runtime-corejs3": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.28.4.tgz", + "integrity": "sha512-h7iEYiW4HebClDEhtvFObtPmIvrd1SSfpI9EhOeKk4CtIK/ngBWFpuhCzhdmRKtg71ylcue+9I6dv54XYO1epQ==", + "license": "MIT", + "dependencies": { + "core-js-pure": "^3.43.0" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } + "node_modules/@breadboard-ai/types": { + "resolved": "packages/types", + "link": true }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" + "node_modules/@breadboard-ai/unified-server": { + "resolved": "packages/unified-server", + "link": true + }, + "node_modules/@breadboard-ai/utils": { + "resolved": "packages/utils", + "link": true + }, + "node_modules/@breadboard-ai/visual-editor": { + "resolved": "packages/visual-editor", + "link": true + }, + "node_modules/@cfworker/json-schema": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.1.1.tgz", + "integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@csstools/color-helpers": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } ], + "license": "MIT-0", "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "freebsd" + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } ], + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" + "node_modules/@csstools/css-color-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.1.0", + "@csstools/css-calc": "^2.1.4" + }, "engines": { - "node": ">=12" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } ], + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.14.tgz", + "integrity": "sha512-zSlIxa20WvMojjpCSy8WrNpcZ61RqfTfX3XTaOeVlGJrt/8HF3YbzgFZa01yTbT4GWQLwfTcC3EB8i3XnB647Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } ], + "license": "MIT-0", "engines": { - "node": ">=12" + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } ], + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">= 4" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=12" + "node": "*" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "netbsd" - ], + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "openbsd" - ], + "node_modules/@google-cloud/paginator": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz", + "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==", + "license": "Apache-2.0", + "dependencies": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + }, "engines": { - "node": ">=12" + "node": ">=14.0.0" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "sunos" - ], + "node_modules/@google-cloud/paginator/node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@google-cloud/projectify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", + "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": ">=14.0.0" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@google-cloud/promisify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", + "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": ">=14" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@google-cloud/storage": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.17.3.tgz", + "integrity": "sha512-gOnCAbFgAYKRozywLsxagdevTF7Gm+2Ncz5u5CQAuOv/2VCa0rdGJWvJFDOftPx1tc+q8TXiC2pEJfFKu+yeMQ==", + "license": "Apache-2.0", + "dependencies": { + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "<4.1.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "duplexify": "^4.1.3", + "fast-xml-parser": "^4.4.1", + "gaxios": "^6.0.2", + "google-auth-library": "^9.6.3", + "html-entities": "^2.5.2", + "mime": "^3.0.0", + "p-limit": "^3.0.1", + "retry-request": "^7.0.0", + "teeny-request": "^9.0.0", + "uuid": "^8.0.0" + }, "engines": { - "node": ">=12" + "node": ">=14" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" + "node_modules/@google-cloud/storage/node_modules/gcp-metadata": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", + "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^6.1.1", + "google-logging-utils": "^0.0.2", + "json-bigint": "^1.0.0" }, "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/rollup": { - "version": "3.29.5", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", - "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", - "license": "MIT", - "bin": { - "rollup": "dist/bin/rollup" + "node": ">=14" + } + }, + "node_modules/@google-cloud/storage/node_modules/google-auth-library": { + "version": "9.15.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz", + "integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" }, "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=14" + } + }, + "node_modules/@google-cloud/storage/node_modules/google-logging-utils": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", + "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" } }, - "node_modules/@11ty/eleventy-plugin-vite/node_modules/vite": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.5.tgz", - "integrity": "sha512-ifW3Lb2sMdX+WU91s3R0FyQlAyLxOzCSCP37ujw0+r5POeHPwe6udWVIElKQq8gk3t7b8rkmvqC6IHBpCff4GQ==", + "node_modules/@google-cloud/storage/node_modules/gtoken": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", "license": "MIT", "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - }, - "bin": { - "vite": "bin/vite.js" + "gaxios": "^6.0.0", + "jws": "^4.0.0" }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "node": ">=14.0.0" } }, - "node_modules/@11ty/eleventy-utils": { - "version": "1.0.2", - "dev": true, + "node_modules/@google-cloud/storage/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", "license": "MIT", - "dependencies": { - "normalize-path": "^3.0.0" + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">=12" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" + "node": ">=10.0.0" } }, - "node_modules/@11ty/eleventy/node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" + "node_modules/@google-cloud/storage/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } }, - "node_modules/@11ty/eleventy/node_modules/entities": { - "version": "3.0.1", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/@google-labs/tsconfig": { + "resolved": "core/tsconfig", + "link": true + }, + "node_modules/@google/genai": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.30.0.tgz", + "integrity": "sha512-3MRcgczBFbUat1wIlZoLJ0vCCfXgm7Qxjh59cZi2X08RgWLtm9hKOspzp7TOg1TV2e26/MLxR2GR5yD5GmBV2w==", + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "ws": "^8.18.0" + }, "engines": { - "node": ">=0.12" + "node": ">=20.0.0" }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.20.1" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } } }, - "node_modules/@11ty/eleventy/node_modules/kleur": { - "version": "4.1.5", + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, "engines": { - "node": ">=6" + "node": ">=10.10.0" } }, - "node_modules/@11ty/eleventy/node_modules/linkify-it": { - "version": "4.0.1", + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { - "uc.micro": "^1.0.1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@11ty/eleventy/node_modules/markdown-it": { - "version": "13.0.2", + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "argparse": "^2.0.1", - "entities": "~3.0.1", - "linkify-it": "^4.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "brace-expansion": "^1.1.7" }, - "bin": { - "markdown-it": "bin/markdown-it.js" + "engines": { + "node": "*" } }, - "node_modules/@11ty/eleventy/node_modules/mdurl": { + "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "MIT" - }, - "node_modules/@11ty/eleventy/node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@11ty/eleventy/node_modules/uc.micro": { - "version": "1.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@11ty/lodash-custom": { - "version": "4.17.21", - "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=14" + "node": ">=12.22" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/11ty" + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@75lb/deep-merge": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@75lb/deep-merge/-/deep-merge-1.1.2.tgz", - "integrity": "sha512-08K9ou5VNbheZFxM5tDWoqjA3ImC50DiuuJ2tj1yEPRfkp8lLLg6XAaJ4On+a0yAXor/8ay5gHnAIshRM44Kpw==", + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", "dependencies": { - "lodash": "^4.17.21", - "typical": "^7.1.1" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=12.17" + "node": ">=12" } }, - "node_modules/@75lb/deep-merge/node_modules/typical": { - "version": "7.1.1", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=12.17" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", "dev": true, - "license": "Apache-2.0", - "peer": true, + "license": "ISC", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "minipass": "^7.0.4" }, "engines": { - "node": ">=6.0.0" + "node": ">=18.0.0" } }, - "node_modules/@andrewbranch/untar.js": { - "version": "1.0.3", - "dev": true + "node_modules/@lit-labs/signals": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@lit-labs/signals/-/signals-0.1.3.tgz", + "integrity": "sha512-P0yWgH5blwVyEwBg+WFspLzeu1i0ypJP1QB0l1Omr9qZLIPsUu0p4Fy2jshOg7oQyha5n163K3GJGeUhQQ682Q==", + "license": "BSD-3-Clause", + "dependencies": { + "lit": "^2.0.0 || ^3.0.0", + "signal-polyfill": "^0.2.0" + } + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.4.0.tgz", + "integrity": "sha512-ficsEARKnmmW5njugNYKipTm4SFnbik7CXtoencDZzmzo/dQ+2Q0bgkzJuoJP20Aj0F+izzJjOqsnkd6F/o1bw==", + "license": "BSD-3-Clause" }, - "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", - "integrity": "sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==", + "node_modules/@lit/context": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.6.tgz", + "integrity": "sha512-M26qDE6UkQbZA2mQ3RjJ3Gzd8TxP+/0obMgE5HfkfLhEEyYE3Bui4A5XHiGPjy0MUGAyxB3QgVuw2ciS0kHn6A==", + "license": "BSD-3-Clause", "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" + "@lit/reactive-element": "^1.6.2 || ^2.1.0" } }, - "node_modules/@apidevtools/json-schema-ref-parser/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "node_modules/@lit/reactive-element": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.1.tgz", + "integrity": "sha512-N+dm5PAYdQ8e6UlywyyrgI2t++wFGXfHx+dSJ1oBrg6FAxUj40jId++EaRm80MKX5JnlH1sBsyZ5h0bcZKemCg==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.4.0" + } }, - "node_modules/@apidevtools/json-schema-ref-parser/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/@lit/task": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lit/task/-/task-1.0.3.tgz", + "integrity": "sha512-1gJGJl8WON+2j0y9xfcD+XsS1rvcy3XDgsIhcdUW++yTR8ESjZW6o7dn8M8a4SZM8NnJe6ynS2cKWwsbfLOurg==", + "license": "BSD-3-Clause", "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "@lit/reactive-element": "^1.0.0 || ^2.0.0" } }, - "node_modules/@arethetypeswrong/cli": { - "version": "0.15.1", + "node_modules/@mapbox/node-pre-gyp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-2.0.0.tgz", + "integrity": "sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "@arethetypeswrong/core": "0.15.1", - "chalk": "^4.1.2", - "cli-table3": "^0.6.3", - "commander": "^10.0.1", - "marked": "^9.1.2", - "marked-terminal": "^6.0.0", - "semver": "^7.5.4" + "consola": "^3.2.3", + "detect-libc": "^2.0.0", + "https-proxy-agent": "^7.0.5", + "node-fetch": "^2.6.7", + "nopt": "^8.0.0", + "semver": "^7.5.3", + "tar": "^7.4.0" }, "bin": { - "attw": "dist/index.js" + "node-pre-gyp": "bin/node-pre-gyp" }, "engines": { "node": ">=18" } }, - "node_modules/@arethetypeswrong/cli/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", + "node_modules/@material/material-color-utilities": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@material/material-color-utilities/-/material-color-utilities-0.3.0.tgz", + "integrity": "sha512-ztmtTd6xwnuh2/xu+Vb01btgV8SQWYCaK56CkRK8gEkWe5TuDyBcYJ0wgkMRn+2VcE9KUmhvkz+N9GHrqw/C0g==", + "license": "Apache-2.0" + }, + "node_modules/@material/web": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@material/web/-/web-2.4.1.tgz", + "integrity": "sha512-0sk9t25acJ72Qv3r0n9r0lgDbPaAKnpm0p+QmEAAwYyZomHxuVbgrrAdtNXaRm7jFyGh+WsTr8bhtvCnpPRFjw==", + "license": "Apache-2.0", + "workspaces": [ + "catalog" + ], "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "lit": "^2.8.0 || ^3.0.0", + "tslib": "^2.4.0" } }, - "node_modules/@arethetypeswrong/cli/node_modules/chalk": { - "version": "4.1.2", - "dev": true, + "node_modules/@maxim_mazurok/gapi.client.calendar-v3": { + "version": "0.1.20251111", + "resolved": "https://registry.npmjs.org/@maxim_mazurok/gapi.client.calendar-v3/-/gapi.client.calendar-v3-0.1.20251111.tgz", + "integrity": "sha512-giWeShOtyJUiOGnnTH6AXkReUXabSGlEi7AuCBfG6/HE6phXUm7FrB/Cc1NlXAHejvKcAREBBWFAh9pV5wd26Q==", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "@types/gapi.client": "*", + "@types/gapi.client.discovery-v1": "*" } }, - "node_modules/@arethetypeswrong/cli/node_modules/commander": { - "version": "10.0.1", - "dev": true, + "node_modules/@maxim_mazurok/gapi.client.discovery-v1": { + "version": "0.4.20200806", + "resolved": "https://registry.npmjs.org/@maxim_mazurok/gapi.client.discovery-v1/-/gapi.client.discovery-v1-0.4.20200806.tgz", + "integrity": "sha512-Jeo/KZqK39DI6ExXHcJ4lqnn1O/wEqboQ6eQ8WnNpu5eJ7wUnX/C5KazOgs1aRhnIB/dVzDe8wm62nmtkMIoaw==", "license": "MIT", - "engines": { - "node": ">=14" + "dependencies": { + "@types/gapi.client": "*", + "@types/gapi.client.discovery-v1": "*" } }, - "node_modules/@arethetypeswrong/cli/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, + "node_modules/@maxim_mazurok/gapi.client.drive-v3": { + "version": "0.1.20251114", + "resolved": "https://registry.npmjs.org/@maxim_mazurok/gapi.client.drive-v3/-/gapi.client.drive-v3-0.1.20251114.tgz", + "integrity": "sha512-Fa57yFZdYb91opntmflWXAY8/VrOGVfFd5xollwWwm2nz5mc0QH0QJkS11v5nh7QD91ExRh3FNTVWCZkNY7eDg==", "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@types/gapi.client": "*", + "@types/gapi.client.discovery-v1": "*" } }, - "node_modules/@arethetypeswrong/cli/node_modules/marked": { - "version": "9.1.6", - "dev": true, + "node_modules/@maxim_mazurok/gapi.client.gmail-v1": { + "version": "0.1.20251110", + "resolved": "https://registry.npmjs.org/@maxim_mazurok/gapi.client.gmail-v1/-/gapi.client.gmail-v1-0.1.20251110.tgz", + "integrity": "sha512-OjXcnJ3CuwUX5PYcvvjYAPz7xN+BlHRU4O+zqT8OJNItCEChfNvUbqydTYKLC6DvhLsoc77eRdH4TjVxYZi8uw==", "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 16" + "dependencies": { + "@types/gapi.client": "*", + "@types/gapi.client.discovery-v1": "*" } }, - "node_modules/@arethetypeswrong/cli/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.22.0.tgz", + "integrity": "sha512-VUpl106XVTCpDmTBil2ehgJZjhyLY2QZikzF8NvTXtLRF1CvO5iEE2UNZdVIUer35vFOwMKYeUGbjJtvPWan3g==", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@arethetypeswrong/core": { - "version": "0.15.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@andrewbranch/untar.js": "^1.0.3", - "fflate": "^0.8.2", - "semver": "^7.5.4", - "ts-expose-internals-conditionally": "1.0.0-empty.0", - "typescript": "5.3.3", - "validate-npm-package-name": "^5.0.0" + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@cfworker/json-schema": "^4.1.1" + }, + "peerDependenciesMeta": { + "@cfworker/json-schema": { + "optional": true + } } }, - "node_modules/@arethetypeswrong/core/node_modules/typescript": { - "version": "5.3.3", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" }, "engines": { - "node": ">=14.17" + "node": ">= 0.6" } }, - "node_modules/@ava/typescript": { - "version": "4.1.0", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", "dependencies": { - "escape-string-regexp": "^5.0.0", - "execa": "^7.1.1" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, - "engines": { - "node": "^14.19 || ^16.15 || ^18 || ^20" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@babel/code-frame": { - "version": "7.24.2", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.2", - "picocolors": "^1.0.0" + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/compat-data": { - "version": "7.24.4", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", - "peer": true, "engines": { - "node": ">=6.9.0" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/@babel/core": { - "version": "7.24.4", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "license": "MIT", - "peer": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" }, "engines": { - "node": ">=6.9.0" + "node": ">= 18" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" + "url": "https://opencollective.com/express" } }, - "node_modules/@babel/generator": { - "version": "7.24.4", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", "license": "MIT", - "peer": true, "dependencies": { - "@babel/types": "^7.24.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.8" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "license": "MIT", - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.8" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "dev": true, - "license": "ISC", - "peer": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "dev": true, - "license": "ISC", - "peer": true + "node_modules/@modelcontextprotocol/sdk/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", - "peer": true, "engines": { - "node": ">=6.9.0" + "node": ">= 0.8" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", - "peer": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "license": "MIT", - "peer": true, "dependencies": { - "@babel/types": "^7.22.5" + "mime-db": "^1.54.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.6" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.3", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.24.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.6" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "dev": true, - "license": "MIT", - "peer": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "side-channel": "^1.1.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=0.6" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", "license": "MIT", - "peer": true, + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, "engines": { - "node": ">=6.9.0" + "node": ">= 18" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", "license": "MIT", - "peer": true, "dependencies": { - "@babel/types": "^7.22.5" + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 18" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", - "peer": true, "dependencies": { - "@babel/types": "^7.22.5" + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.6" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "dev": true, + "node_modules/@napi-rs/canvas": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.82.tgz", + "integrity": "sha512-FGjyUBoF0sl1EenSiE4UV2WYu76q6F9GSYedq5EiOCOyGYoQ/Owulcv6rd7v/tWOpljDDtefXXIaOCJrVKem4w==", "license": "MIT", + "optional": true, + "workspaces": [ + "e2e/*" + ], "engines": { - "node": ">=6.9.0" + "node": ">= 10" + }, + "optionalDependencies": { + "@napi-rs/canvas-android-arm64": "0.1.82", + "@napi-rs/canvas-darwin-arm64": "0.1.82", + "@napi-rs/canvas-darwin-x64": "0.1.82", + "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.82", + "@napi-rs/canvas-linux-arm64-gnu": "0.1.82", + "@napi-rs/canvas-linux-arm64-musl": "0.1.82", + "@napi-rs/canvas-linux-riscv64-gnu": "0.1.82", + "@napi-rs/canvas-linux-x64-gnu": "0.1.82", + "@napi-rs/canvas-linux-x64-musl": "0.1.82", + "@napi-rs/canvas-win32-x64-msvc": "0.1.82" + } + }, + "node_modules/@napi-rs/canvas-android-arm64": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.82.tgz", + "integrity": "sha512-bvZhN0iI54ouaQOrgJV96H2q7J3ZoufnHf4E1fUaERwW29Rz4rgicohnAg4venwBJZYjGl5Yl3CGmlAl1LZowQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "dev": true, + "node_modules/@napi-rs/canvas-darwin-arm64": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.82.tgz", + "integrity": "sha512-InuBHKCyuFqhNwNr4gpqazo5Xp6ltKflqOLiROn4hqAS8u21xAHyYCJRgHwd+a5NKmutFTaRWeUIT/vxWbU/iw==", + "cpu": [ + "arm64" + ], "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" + "node": ">= 10" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "dev": true, + "node_modules/@napi-rs/canvas-darwin-x64": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.82.tgz", + "integrity": "sha512-aQGV5Ynn96onSXcuvYb2y7TRXD/t4CL2EGmnGqvLyeJX1JLSNisKQlWN/1bPDDXymZYSdUqbXehj5qzBlOx+RQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "peer": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" + "node": ">= 10" } }, - "node_modules/@babel/helpers": { - "version": "7.24.4", - "dev": true, + "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.82.tgz", + "integrity": "sha512-YIUpmHWeHGGRhWitT1KJkgj/JPXPfc9ox8oUoyaGPxolLGPp5AxJkq8wIg8CdFGtutget968dtwmx71m8o3h5g==", + "cpu": [ + "arm" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">= 10" } }, - "node_modules/@babel/highlight": { - "version": "7.24.2", - "dev": true, + "node_modules/@napi-rs/canvas-linux-arm64-gnu": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.82.tgz", + "integrity": "sha512-AwLzwLBgmvk7kWeUgItOUor/QyG31xqtD26w1tLpf4yE0hiXTGp23yc669aawjB6FzgIkjh1NKaNS52B7/qEBQ==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">= 10" } }, - "node_modules/@babel/parser": { - "version": "7.24.4", - "dev": true, + "node_modules/@napi-rs/canvas-linux-arm64-musl": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.82.tgz", + "integrity": "sha512-moZWuqepAwWBffdF4JDadt8TgBD02iMhG6I1FHZf8xO20AsIp9rB+p0B8Zma2h2vAF/YMjeFCDmW5un6+zZz9g==", + "cpu": [ + "arm64" + ], "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.0.0" + "node": ">= 10" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "dev": true, + "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.82.tgz", + "integrity": "sha512-w9++2df2kG9eC9LWYIHIlMLuhIrKGQYfUxs97CwgxYjITeFakIRazI9LYWgVzEc98QZ9x9GQvlicFsrROV59MQ==", + "cpu": [ + "riscv64" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "dev": true, + "node_modules/@napi-rs/canvas-linux-x64-gnu": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.82.tgz", + "integrity": "sha512-lZulOPwrRi6hEg/17CaqdwWEUfOlIJuhXxincx1aVzsVOCmyHf+xFq4i6liJl1P+x2v6Iz2Z/H5zHvXJCC7Bwg==", + "cpu": [ + "x64" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "dev": true, + "node_modules/@napi-rs/canvas-linux-x64-musl": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.82.tgz", + "integrity": "sha512-Be9Wf5RTv1w6GXlTph55K3PH3vsAh1Ax4T1FQY1UYM0QfD0yrwGdnJ8/fhqw7dEgMjd59zIbjJQC8C3msbGn5g==", + "cpu": [ + "x64" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "dev": true, + "node_modules/@napi-rs/canvas-win32-x64-msvc": { + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.82.tgz", + "integrity": "sha512-LN/i8VrvxTDmEEK1c10z2cdOTkWT76LlTGtyZe5Kr1sqoSomKeExAjbilnu1+oee5lZUgS5yfZ2LNlVhCeARuw==", + "cpu": [ + "x64" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 8" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.1", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 8" } }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "dev": true, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "engines": { + "node": ">=14" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "dev": true, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.2.tgz", + "integrity": "sha512-yDPzwsgiFO26RJA4nZo8I+xqzh7sJTZIWQOxn+/XOdPE31lAvLIYCKqjV+lNH/vxE2L2iH3plKxDCRK6i+CwhA==", + "cpu": [ + "arm" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "dev": true, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.2.tgz", + "integrity": "sha512-k8FontTxIE7b0/OGKeSN5B6j25EuppBcWM33Z19JoVT7UTXFSo3D9CdU39wGTeb29NO3XxpMNauh09B+Ibw+9g==", + "cpu": [ + "arm64" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.1", - "dev": true, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.2.tgz", + "integrity": "sha512-A6s4gJpomNBtJ2yioj8bflM2oogDwzUiMl2yNJ2v9E7++sHrSrsQ29fOfn5DM/iCzpWcebNYEdXpaK4tr2RhfQ==", + "cpu": [ + "arm64" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", - "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@babel/template": { - "version": "7.24.0", - "dev": true, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.2.tgz", + "integrity": "sha512-e6XqVmXlHrBlG56obu9gDRPW3O3hLxpwHpLsBJvuI8qqnsrtSZ9ERoWUXtPOkY8c78WghyPHZdmPhHLWNdAGEw==", + "cpu": [ + "x64" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@babel/traverse": { - "version": "7.24.1", - "dev": true, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.2.tgz", + "integrity": "sha512-v0E9lJW8VsrwPux5Qe5CwmH/CF/2mQs6xU1MF3nmUxmZUCHazCjLgYvToOk+YuuUqLQBio1qkkREhxhc656ViA==", + "cpu": [ + "arm64" + ], "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "dev": true, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.2.tgz", + "integrity": "sha512-ClAmAPx3ZCHtp6ysl4XEhWU69GUB1D+s7G9YjHGhIGCSrsg00nEGRRZHmINYxkdoJehde8VIsDC5t9C0gb6yqA==", + "cpu": [ + "x64" + ], "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@babel/types": { - "version": "7.24.0", - "dev": true, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.2.tgz", + "integrity": "sha512-EPlb95nUsz6Dd9Qy13fI5kUPXNSljaG9FiJ4YUGU1O/Q77i5DYFW5KR8g1OzTcdZUqQQ1KdDqsTohdFVwCwjqg==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "dev": true, - "license": "MIT" + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.2.tgz", + "integrity": "sha512-BOmnVW+khAUX+YZvNfa0tGTEMVVEerOxN0pDk2E6N6DsEIa2Ctj48FOMfNDdrwinocKaC7YXUZ1pHlKpnkja/Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@breadboard-ai/board-server": { - "resolved": "packages/board-server", - "link": true + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.2.tgz", + "integrity": "sha512-Xt2byDZ+6OVNuREgBXr4+CZDJtrVso5woFtpKdGPhpTPHcNG7D8YXeQzpNbFRxzTVqJf7kvPMCub/pcGUWgBjA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@breadboard-ai/board-server-management": { - "resolved": "packages/board-server-management", - "link": true + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.2.tgz", + "integrity": "sha512-+LdZSldy/I9N8+klim/Y1HsKbJ3BbInHav5qE9Iy77dtHC/pibw1SR/fXlWyAk0ThnpRKoODwnAuSjqxFRDHUQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@breadboard-ai/board-server-utils": { - "resolved": "packages/board-server-utils", - "link": true + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.2.tgz", + "integrity": "sha512-8ms8sjmyc1jWJS6WdNSA23rEfdjWB30LH8Wqj0Cqvv7qSHnvw6kgMMXRdop6hkmGPlyYBdRPkjJnj3KCUHV/uQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@breadboard-ai/build": { - "resolved": "packages/build", - "link": true - }, - "node_modules/@breadboard-ai/build-code": { - "resolved": "packages/build-code", - "link": true - }, - "node_modules/@breadboard-ai/connection-server": { - "resolved": "packages/connection-server", - "link": true - }, - "node_modules/@breadboard-ai/data-store": { - "resolved": "packages/data-store", - "link": true - }, - "node_modules/@breadboard-ai/example-boards": { - "resolved": "packages/example-boards", - "link": true - }, - "node_modules/@breadboard-ai/google-drive-kit": { - "resolved": "packages/google-drive-kit", - "link": true - }, - "node_modules/@breadboard-ai/idb-board-server": { - "resolved": "packages/idb-board-server", - "link": true - }, - "node_modules/@breadboard-ai/import": { - "resolved": "packages/import", - "link": true - }, - "node_modules/@breadboard-ai/manifest": { - "resolved": "packages/manifest", - "link": true - }, - "node_modules/@breadboard-ai/python-wasm": { - "resolved": "packages/python-wasm", - "link": true - }, - "node_modules/@breadboard-ai/remote-board-server": { - "resolved": "packages/remote-board-server", - "link": true - }, - "node_modules/@breadboard-ai/shared-ui": { - "resolved": "packages/shared-ui", - "link": true - }, - "node_modules/@breadboard-ai/visual-editor": { - "resolved": "packages/visual-editor", - "link": true - }, - "node_modules/@changesets/apply-release-plan": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.5.tgz", - "integrity": "sha512-1cWCk+ZshEkSVEZrm2fSj1Gz8sYvxgUL4Q78+1ZZqeqfuevPTPk033/yUZ3df8BKMohkqqHfzj0HOOrG0KtXTw==", - "dev": true, - "dependencies": { - "@changesets/config": "^3.0.3", - "@changesets/get-version-range-type": "^0.4.0", - "@changesets/git": "^3.0.1", - "@changesets/should-skip-package": "^0.1.1", - "@changesets/types": "^6.0.0", - "@manypkg/get-packages": "^1.1.3", - "detect-indent": "^6.0.0", - "fs-extra": "^7.0.1", - "lodash.startcase": "^4.4.0", - "outdent": "^0.5.0", - "prettier": "^2.7.1", - "resolve-from": "^5.0.0", - "semver": "^7.5.3" - } - }, - "node_modules/@changesets/apply-release-plan/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/@changesets/assemble-release-plan": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-6.0.4.tgz", - "integrity": "sha512-nqICnvmrwWj4w2x0fOhVj2QEGdlUuwVAwESrUo5HLzWMI1rE5SWfsr9ln+rDqWB6RQ2ZyaMZHUcU7/IRaUJS+Q==", - "dev": true, - "dependencies": { - "@changesets/errors": "^0.2.0", - "@changesets/get-dependents-graph": "^2.1.2", - "@changesets/should-skip-package": "^0.1.1", - "@changesets/types": "^6.0.0", - "@manypkg/get-packages": "^1.1.3", - "semver": "^7.5.3" - } - }, - "node_modules/@changesets/changelog-git": { - "version": "0.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@changesets/types": "^6.0.0" - } - }, - "node_modules/@changesets/cli": { - "version": "2.27.8", - "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.27.8.tgz", - "integrity": "sha512-gZNyh+LdSsI82wBSHLQ3QN5J30P4uHKJ4fXgoGwQxfXwYFTJzDdvIJasZn8rYQtmKhyQuiBj4SSnLuKlxKWq4w==", - "dev": true, - "dependencies": { - "@changesets/apply-release-plan": "^7.0.5", - "@changesets/assemble-release-plan": "^6.0.4", - "@changesets/changelog-git": "^0.2.0", - "@changesets/config": "^3.0.3", - "@changesets/errors": "^0.2.0", - "@changesets/get-dependents-graph": "^2.1.2", - "@changesets/get-release-plan": "^4.0.4", - "@changesets/git": "^3.0.1", - "@changesets/logger": "^0.1.1", - "@changesets/pre": "^2.0.1", - "@changesets/read": "^0.6.1", - "@changesets/should-skip-package": "^0.1.1", - "@changesets/types": "^6.0.0", - "@changesets/write": "^0.3.2", - "@manypkg/get-packages": "^1.1.3", - "@types/semver": "^7.5.0", - "ansi-colors": "^4.1.3", - "ci-info": "^3.7.0", - "enquirer": "^2.3.0", - "external-editor": "^3.1.0", - "fs-extra": "^7.0.1", - "mri": "^1.2.0", - "outdent": "^0.5.0", - "p-limit": "^2.2.0", - "package-manager-detector": "^0.2.0", - "picocolors": "^1.1.0", - "resolve-from": "^5.0.0", - "semver": "^7.5.3", - "spawndamnit": "^2.0.0", - "term-size": "^2.1.0" - }, - "bin": { - "changeset": "bin.js" - } - }, - "node_modules/@changesets/config": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.0.3.tgz", - "integrity": "sha512-vqgQZMyIcuIpw9nqFIpTSNyc/wgm/Lu1zKN5vECy74u95Qx/Wa9g27HdgO4NkVAaq+BGA8wUc/qvbvVNs93n6A==", - "dev": true, - "dependencies": { - "@changesets/errors": "^0.2.0", - "@changesets/get-dependents-graph": "^2.1.2", - "@changesets/logger": "^0.1.1", - "@changesets/types": "^6.0.0", - "@manypkg/get-packages": "^1.1.3", - "fs-extra": "^7.0.1", - "micromatch": "^4.0.2" - } - }, - "node_modules/@changesets/errors": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.2.0.tgz", - "integrity": "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==", - "dev": true, - "dependencies": { - "extendable-error": "^0.1.5" - } - }, - "node_modules/@changesets/get-dependents-graph": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-2.1.2.tgz", - "integrity": "sha512-sgcHRkiBY9i4zWYBwlVyAjEM9sAzs4wYVwJUdnbDLnVG3QwAaia1Mk5P8M7kraTOZN+vBET7n8KyB0YXCbFRLQ==", - "dev": true, - "dependencies": { - "@changesets/types": "^6.0.0", - "@manypkg/get-packages": "^1.1.3", - "picocolors": "^1.1.0", - "semver": "^7.5.3" - } - }, - "node_modules/@changesets/get-release-plan": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.4.tgz", - "integrity": "sha512-SicG/S67JmPTrdcc9Vpu0wSQt7IiuN0dc8iR5VScnnTVPfIaLvKmEGRvIaF0kcn8u5ZqLbormZNTO77bCEvyWw==", - "dev": true, - "dependencies": { - "@changesets/assemble-release-plan": "^6.0.4", - "@changesets/config": "^3.0.3", - "@changesets/pre": "^2.0.1", - "@changesets/read": "^0.6.1", - "@changesets/types": "^6.0.0", - "@manypkg/get-packages": "^1.1.3" - } - }, - "node_modules/@changesets/get-version-range-type": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.4.0.tgz", - "integrity": "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==", - "dev": true - }, - "node_modules/@changesets/git": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@changesets/git/-/git-3.0.1.tgz", - "integrity": "sha512-pdgHcYBLCPcLd82aRcuO0kxCDbw/yISlOtkmwmE8Odo1L6hSiZrBOsRl84eYG7DRCab/iHnOkWqExqc4wxk2LQ==", - "dev": true, - "dependencies": { - "@changesets/errors": "^0.2.0", - "@manypkg/get-packages": "^1.1.3", - "is-subdir": "^1.1.1", - "micromatch": "^4.0.2", - "spawndamnit": "^2.0.0" - } - }, - "node_modules/@changesets/logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.1.1.tgz", - "integrity": "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==", - "dev": true, - "dependencies": { - "picocolors": "^1.1.0" - } - }, - "node_modules/@changesets/parse": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.4.0.tgz", - "integrity": "sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==", - "dev": true, - "dependencies": { - "@changesets/types": "^6.0.0", - "js-yaml": "^3.13.1" - } - }, - "node_modules/@changesets/pre": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-2.0.1.tgz", - "integrity": "sha512-vvBJ/If4jKM4tPz9JdY2kGOgWmCowUYOi5Ycv8dyLnEE8FgpYYUo1mgJZxcdtGGP3aG8rAQulGLyyXGSLkIMTQ==", - "dev": true, - "dependencies": { - "@changesets/errors": "^0.2.0", - "@changesets/types": "^6.0.0", - "@manypkg/get-packages": "^1.1.3", - "fs-extra": "^7.0.1" - } - }, - "node_modules/@changesets/read": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.1.tgz", - "integrity": "sha512-jYMbyXQk3nwP25nRzQQGa1nKLY0KfoOV7VLgwucI0bUO8t8ZLCr6LZmgjXsiKuRDc+5A6doKPr9w2d+FEJ55zQ==", - "dev": true, - "dependencies": { - "@changesets/git": "^3.0.1", - "@changesets/logger": "^0.1.1", - "@changesets/parse": "^0.4.0", - "@changesets/types": "^6.0.0", - "fs-extra": "^7.0.1", - "p-filter": "^2.1.0", - "picocolors": "^1.1.0" - } - }, - "node_modules/@changesets/should-skip-package": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@changesets/should-skip-package/-/should-skip-package-0.1.1.tgz", - "integrity": "sha512-H9LjLbF6mMHLtJIc/eHR9Na+MifJ3VxtgP/Y+XLn4BF7tDTEN1HNYtH6QMcjP1uxp9sjaFYmW8xqloaCi/ckTg==", - "dev": true, - "dependencies": { - "@changesets/types": "^6.0.0", - "@manypkg/get-packages": "^1.1.3" - } - }, - "node_modules/@changesets/types": { - "version": "6.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@changesets/write": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@changesets/write/-/write-0.3.2.tgz", - "integrity": "sha512-kDxDrPNpUgsjDbWBvUo27PzKX4gqeKOlhibaOXDJA6kuBisGqNHv/HwGJrAu8U/dSf8ZEFIeHIPtvSlZI1kULw==", - "dev": true, - "dependencies": { - "@changesets/types": "^6.0.0", - "fs-extra": "^7.0.1", - "human-id": "^1.0.2", - "prettier": "^2.7.1" - } - }, - "node_modules/@changesets/write/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/@codemirror/autocomplete": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.1.tgz", - "integrity": "sha512-iWHdj/B1ethnHRTwZj+C1obmmuCzquH29EbcKr0qIjA9NfDeBDJ7vs+WOHsFeLeflE4o+dHfYndJloMKHUkWUA==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0" - }, - "peerDependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@codemirror/commands": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.2.tgz", - "integrity": "sha512-Fq7eWOl1Rcbrfn6jD8FPCj9Auaxdm5nIK5RYOeW7ughnd/rY5AmPg6b+CfsG39ZHdwiwe8lde3q8uR7CF5S0yQ==", - "dependencies": { - "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.27.0", - "@lezer/common": "^1.1.0" - } - }, - "node_modules/@codemirror/lang-javascript": { - "version": "6.2.2", - "license": "MIT", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/language": "^6.6.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.17.0", - "@lezer/common": "^1.0.0", - "@lezer/javascript": "^1.0.0" - } - }, - "node_modules/@codemirror/language": { - "version": "6.10.1", - "license": "MIT", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.23.0", - "@lezer/common": "^1.1.0", - "@lezer/highlight": "^1.0.0", - "@lezer/lr": "^1.0.0", - "style-mod": "^4.0.0" - } - }, - "node_modules/@codemirror/lint": { - "version": "6.5.0", - "license": "MIT", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - }, - "node_modules/@codemirror/search": { - "version": "6.5.6", - "license": "MIT", - "dependencies": { - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", - "crelt": "^1.0.5" - } - }, - "node_modules/@codemirror/state": { - "version": "6.4.1", - "license": "MIT" - }, - "node_modules/@codemirror/view": { - "version": "6.28.0", - "license": "MIT", - "dependencies": { - "@codemirror/state": "^6.4.0", - "style-mod": "^4.1.0", - "w3c-keyname": "^2.2.4" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@dagrejs/dagre": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@dagrejs/dagre/-/dagre-1.1.4.tgz", - "integrity": "sha512-QUTc54Cg/wvmlEUxB+uvoPVKFazM1H18kVHBQNmK2NbrDR5ihOCR6CXLnDSZzMcSQKJtabPUWridBOlJM3WkDg==", - "dependencies": { - "@dagrejs/graphlib": "2.2.4" - } - }, - "node_modules/@dagrejs/graphlib": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@dagrejs/graphlib/-/graphlib-2.2.4.tgz", - "integrity": "sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw==", - "engines": { - "node": ">17.0.0" - } - }, - "node_modules/@definitelytyped/dtslint": { - "version": "0.2.23", - "resolved": "https://registry.npmjs.org/@definitelytyped/dtslint/-/dtslint-0.2.23.tgz", - "integrity": "sha512-cx5SOyncwMCuLyfJC12GI5I1+4O6RnHxDhYk+BsT5ZZDjpS0UMdebvdcVEk9bMcZNZkczAiJweDUuDtdx98d8w==", - "dev": true, - "dependencies": { - "@arethetypeswrong/cli": "0.15.1", - "@arethetypeswrong/core": "0.15.1", - "@definitelytyped/header-parser": "0.2.12", - "@definitelytyped/typescript-packages": "0.1.4", - "@definitelytyped/typescript-versions": "0.1.4", - "@definitelytyped/utils": "0.1.7", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "@typescript-eslint/types": "^7.14.1", - "@typescript-eslint/typescript-estree": "^7.14.1", - "@typescript-eslint/utils": "^7.14.1", - "eslint": "^8.57.0", - "eslint-plugin-import": "^2.29.1", - "semver": "^7.5.4", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "dtslint": "dist/index.js" - }, - "engines": { - "node": ">=18.18.0" - }, - "peerDependencies": { - "typescript": ">= 3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.7.0-dev || >= 3.8.0-dev || >= 3.9.0-dev || >= 4.0.0-dev || >=5.0.0-dev" - } - }, - "node_modules/@definitelytyped/header-parser": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@definitelytyped/header-parser/-/header-parser-0.2.12.tgz", - "integrity": "sha512-UYtSXiLMhzRFKh7xHMkgiWsscgHxIndmjetaptZMMS0EOvfhUTuEM68GpjiCtz5shXw22Vacs1vDTAkKGDhNmg==", - "dev": true, - "dependencies": { - "@definitelytyped/typescript-versions": "0.1.4", - "@definitelytyped/utils": "0.1.7", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@definitelytyped/typescript-packages": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@definitelytyped/typescript-packages/-/typescript-packages-0.1.4.tgz", - "integrity": "sha512-eo+o306xW8B+hHWV8HMZYv/la/tHPNE+zrcbDdHanRAmCcH6WLDwggLk7hk6wXShHUTVDMA+y2nwypXi0jmmAg==", - "dev": true, - "dependencies": { - "@definitelytyped/typescript-versions": "0.1.4", - "typescript-4.8": "npm:typescript@~4.8.0-0", - "typescript-4.9": "npm:typescript@~4.9.0-0", - "typescript-5.0": "npm:typescript@~5.0.0-0", - "typescript-5.1": "npm:typescript@~5.1.0-0", - "typescript-5.2": "npm:typescript@~5.2.0-0", - "typescript-5.3": "npm:typescript@~5.3.0-0", - "typescript-5.4": "npm:typescript@~5.4.0-0", - "typescript-5.5": "npm:typescript@~5.5.0-0", - "typescript-5.6": "npm:typescript@~5.6.0-0", - "typescript-5.7": "npm:typescript@~5.7.0-0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@definitelytyped/typescript-versions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@definitelytyped/typescript-versions/-/typescript-versions-0.1.4.tgz", - "integrity": "sha512-4Rz5kCpyxofwXCtBQaNfmWYXZcH0sMJxpbIgJzS+PAxgFCAa9W+2Jil7rrkpzsjx9E7+zOPukbXBXjyXohcyuQ==", - "dev": true, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@definitelytyped/utils": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@definitelytyped/utils/-/utils-0.1.7.tgz", - "integrity": "sha512-t58AeNg6+mvyMnBHyPC6JQqWMW0Iwyb+vlpBz4V0d0iDY9H8gGCnLFg9vtN1nC+JXfTXBlf9efu9unMUeaPCiA==", - "dev": true, - "dependencies": { - "@qiwi/npm-registry-client": "^8.9.1", - "@types/node": "^18.19.7", - "cachedir": "^2.0.0", - "charm": "^1.0.2", - "minimatch": "^9.0.3", - "tar": "^6.2.1", - "tar-stream": "^3.1.6", - "which": "^4.0.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@definitelytyped/utils/node_modules/@types/node": { - "version": "18.19.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.45.tgz", - "integrity": "sha512-VZxPKNNhjKmaC1SUYowuXSRSMGyQGmQjvvA1xE4QZ0xce2kLtEhPDS+kqpCPBZYgqblCLQ2DAjSzmgCM5auvhA==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@definitelytyped/utils/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "engines": { - "node": ">=16" - } - }, - "node_modules/@definitelytyped/utils/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "dev": true, - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^16.13.0 || >=18.0.0" - } - }, - "node_modules/@effect/schema": { - "version": "0.71.1", - "resolved": "https://registry.npmjs.org/@effect/schema/-/schema-0.71.1.tgz", - "integrity": "sha512-XvFttkuBUL3s4ofZ+OVE4Pagb4wsPG8laSS8iO5lVI9Yt1zIM49uxlYIA2BJ45jjS3MdplUepC0NilotKnjU2A==", - "dev": true, - "dependencies": { - "fast-check": "^3.21.0" - }, - "peerDependencies": { - "effect": "^3.6.5" - } - }, - "node_modules/@esbuild-plugins/node-globals-polyfill": { - "version": "0.2.3", - "dev": true, - "license": "ISC", - "peerDependencies": { - "esbuild": "*" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", - "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", - "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@esm-bundle/chai": { - "version": "4.3.4-fix.0", - "resolved": "https://registry.npmjs.org/@esm-bundle/chai/-/chai-4.3.4-fix.0.tgz", - "integrity": "sha512-26SKdM4uvDWlY8/OOOxSB1AqQWeBosCX3wRYUZO7enTAj03CtVxIiCimYVG2WpULcyV51qapK4qTovwkUr5Mlw==", - "dev": true, - "dependencies": { - "@types/chai": "^4.2.12" - } - }, - "node_modules/@fastify/busboy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.0.0.tgz", - "integrity": "sha512-83rnH2nCvclWaPQQKvkJ2pdOjG4TZyEVuFDnlOF6KP08lDaaceVyw/W63mDuafQT+MKHCvXIPpE5uYWeM0rT4w==" - }, - "node_modules/@firebase/app-check-interop-types": { - "version": "0.3.1", - "license": "Apache-2.0" - }, - "node_modules/@firebase/app-types": { - "version": "0.9.1", - "license": "Apache-2.0" - }, - "node_modules/@firebase/auth-interop-types": { - "version": "0.2.2", - "license": "Apache-2.0" - }, - "node_modules/@firebase/component": { - "version": "0.6.6", - "license": "Apache-2.0", - "dependencies": { - "@firebase/util": "1.9.5", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/database": { - "version": "1.0.4", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.1", - "@firebase/auth-interop-types": "0.2.2", - "@firebase/component": "0.6.6", - "@firebase/logger": "0.4.1", - "@firebase/util": "1.9.5", - "faye-websocket": "0.11.4", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/database-compat": { - "version": "1.0.4", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.6.6", - "@firebase/database": "1.0.4", - "@firebase/database-types": "1.0.2", - "@firebase/logger": "0.4.1", - "@firebase/util": "1.9.5", - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/database-types": { - "version": "1.0.2", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-types": "0.9.1", - "@firebase/util": "1.9.5" - } - }, - "node_modules/@firebase/logger": { - "version": "0.4.1", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@firebase/util": { - "version": "1.9.5", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@google-cloud/firestore": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.10.0.tgz", - "integrity": "sha512-VFNhdHvfnmqcHHs6YhmSNHHxQqaaD64GwiL0c+e1qz85S8SWZPC2XFRf8p9yHRTF40Kow424s1KBU9f0fdQa+Q==", - "dependencies": { - "@opentelemetry/api": "^1.3.0", - "fast-deep-equal": "^3.1.1", - "functional-red-black-tree": "^1.0.1", - "google-gax": "^4.3.3", - "protobufjs": "^7.2.6" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@google-cloud/paginator": { - "version": "5.0.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "arrify": "^2.0.0", - "extend": "^3.0.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@google-cloud/paginator/node_modules/arrify": { - "version": "2.0.1", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@google-cloud/projectify": { - "version": "4.0.0", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@google-cloud/promisify": { - "version": "4.0.0", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/secret-manager": { - "version": "5.6.0", - "license": "Apache-2.0", - "dependencies": { - "google-gax": "^4.0.3" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@google-cloud/storage": { - "version": "7.9.0", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@google-cloud/paginator": "^5.0.0", - "@google-cloud/projectify": "^4.0.0", - "@google-cloud/promisify": "^4.0.0", - "abort-controller": "^3.0.0", - "async-retry": "^1.3.3", - "compressible": "^2.0.12", - "duplexify": "^4.1.3", - "ent": "^2.2.0", - "fast-xml-parser": "^4.3.0", - "gaxios": "^6.0.2", - "google-auth-library": "^9.6.3", - "mime": "^3.0.0", - "mime-types": "^2.0.8", - "p-limit": "^3.0.1", - "retry-request": "^7.0.0", - "teeny-request": "^9.0.0", - "uuid": "^8.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/storage/node_modules/p-limit": { - "version": "3.1.0", - "license": "MIT", - "optional": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@google-labs/agent-kit": { - "resolved": "packages/agent-kit", - "link": true - }, - "node_modules/@google-labs/breadboard": { - "resolved": "packages/breadboard", - "link": true - }, - "node_modules/@google-labs/breadboard-cli": { - "resolved": "packages/breadboard-cli", - "link": true - }, - "node_modules/@google-labs/breadboard-schema": { - "resolved": "packages/schema", - "link": true - }, - "node_modules/@google-labs/breadboard-website": { - "resolved": "packages/website", - "link": true - }, - "node_modules/@google-labs/core-kit": { - "resolved": "packages/core-kit", - "link": true - }, - "node_modules/@google-labs/discovery-types": { - "resolved": "packages/discovery-types", - "link": true - }, - "node_modules/@google-labs/gemini-kit": { - "resolved": "packages/gemini-kit", - "link": true - }, - "node_modules/@google-labs/json-kit": { - "resolved": "packages/json-kit", - "link": true - }, - "node_modules/@google-labs/node-nursery-web": { - "resolved": "packages/node-nursery-web", - "link": true - }, - "node_modules/@google-labs/node-proxy-server": { - "resolved": "packages/node-proxy-server", - "link": true - }, - "node_modules/@google-labs/palm-kit": { - "resolved": "packages/palm-kit", - "link": true - }, - "node_modules/@google-labs/palm-lite": { - "version": "0.0.3", - "license": "Apache-2.0" - }, - "node_modules/@google-labs/template-kit": { - "resolved": "packages/template-kit", - "link": true - }, - "node_modules/@google-labs/tsconfig": { - "resolved": "core/tsconfig", - "link": true - }, - "node_modules/@grpc/grpc-js": { - "version": "1.10.9", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.9.tgz", - "integrity": "sha512-5tcgUctCG0qoNyfChZifz2tJqbRbXVO9J7X6duFcOjY3HUNCxg5D0ZCK7EP9vIcZ0zRpLU9bWkyCqVCLZ46IbQ==", - "dependencies": { - "@grpc/proto-loader": "^0.7.13", - "@js-sdsl/ordered-map": "^4.4.2" - }, - "engines": { - "node": ">=12.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.7.13", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@hapi/bourne": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-3.0.0.tgz", - "integrity": "sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==", - "dev": true - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true - }, - "node_modules/@iarna/toml": { - "version": "2.2.5", - "dev": true, - "license": "ISC" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/console/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/core/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/core/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/core/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/core/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/reporters/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/reporters/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@jest/reporters/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@jest/reporters/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/reporters/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@jest/reporters/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/reporters/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map/node_modules/callsites": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/transform/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/transform/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/transform/node_modules/write-file-atomic": { - "version": "4.0.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/types/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "devOptional": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@js-sdsl/ordered-map": { - "version": "4.4.2", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" - }, - "node_modules/@kitql/helpers": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@kitql/helpers/-/helpers-0.8.10.tgz", - "integrity": "sha512-r9m0eQyjy3Z2sdeXA8wRGl2tgKtZ9puPuZ3vm9Cv3WMMWVmbKVzUJvF+4UucsHzT9xECFbO9lcQu7lIb774PPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esm-env": "^1.0.0" - }, - "engines": { - "node": "^16.14 || >=18" - } - }, - "node_modules/@koa/cors": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@koa/cors/-/cors-5.0.0.tgz", - "integrity": "sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw==", - "dev": true, - "dependencies": { - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@lezer/common": { - "version": "1.2.1", - "license": "MIT" - }, - "node_modules/@lezer/highlight": { - "version": "1.2.0", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@lezer/javascript": { - "version": "1.4.14", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.2.0", - "@lezer/highlight": "^1.1.3", - "@lezer/lr": "^1.3.0" - } - }, - "node_modules/@lezer/lr": { - "version": "1.4.0", - "license": "MIT", - "dependencies": { - "@lezer/common": "^1.0.0" - } - }, - "node_modules/@lit-labs/ssr-dom-shim": { - "version": "1.2.0", - "license": "BSD-3-Clause" - }, - "node_modules/@lit/context": { - "version": "1.1.2", - "license": "BSD-3-Clause", - "dependencies": { - "@lit/reactive-element": "^1.6.2 || ^2.0.0" - } - }, - "node_modules/@lit/reactive-element": { - "version": "2.0.4", - "license": "BSD-3-Clause", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0" - } - }, - "node_modules/@lit/task": { - "version": "1.0.1", - "license": "BSD-3-Clause", - "dependencies": { - "@lit/reactive-element": "^1.0.0 || ^2.0.0" - } - }, - "node_modules/@manypkg/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.5.5", - "@types/node": "^12.7.1", - "find-up": "^4.1.0", - "fs-extra": "^8.1.0" - } - }, - "node_modules/@manypkg/find-root/node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "dev": true - }, - "node_modules/@manypkg/find-root/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@manypkg/get-packages": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz", - "integrity": "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.5.5", - "@changesets/types": "^4.0.1", - "@manypkg/find-root": "^1.1.0", - "fs-extra": "^8.1.0", - "globby": "^11.0.0", - "read-yaml-file": "^1.1.0" - } - }, - "node_modules/@manypkg/get-packages/node_modules/@changesets/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@changesets/types/-/types-4.1.0.tgz", - "integrity": "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==", - "dev": true - }, - "node_modules/@manypkg/get-packages/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@mdn/browser-compat-data": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-4.2.1.tgz", - "integrity": "sha512-EWUguj2kd7ldmrF9F+vI5hUOralPd+sdsUnYbRy33vZTuZkduC1shE9TtEMEjAQwyfyMb4ole5KtjF8MsnQOlA==", - "dev": true - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@pixi/colord": { - "version": "2.9.6", - "license": "MIT" - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "license": "BSD-3-Clause" - }, - "node_modules/@puppeteer/browsers": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.4.0.tgz", - "integrity": "sha512-x8J1csfIygOwf6D6qUAZ0ASk3z63zPb7wkNeHRerCMh82qWKUrOgkuP005AJC8lDL6/evtXETGEJVcwykKT4/g==", - "dev": true, - "dependencies": { - "debug": "^4.3.6", - "extract-zip": "^2.0.1", - "progress": "^2.0.3", - "proxy-agent": "^6.4.0", - "semver": "^7.6.3", - "tar-fs": "^3.0.6", - "unbzip2-stream": "^1.4.3", - "yargs": "^17.7.2" - }, - "bin": { - "browsers": "lib/cjs/main-cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@qiwi/npm-registry-client": { - "version": "8.9.1", - "resolved": "https://registry.npmjs.org/@qiwi/npm-registry-client/-/npm-registry-client-8.9.1.tgz", - "integrity": "sha512-rZF+mG+NfijR0SHphhTLHRr4aM4gtfdwoAMY6we2VGQam8vkN1cxGG1Lg/Llrj8Dd0Mu6VjdFQRyMMRZxtZR2A==", - "dev": true, - "dependencies": { - "concat-stream": "^2.0.0", - "graceful-fs": "^4.2.4", - "normalize-package-data": "~1.0.1 || ^2.0.0 || ^3.0.0", - "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^8.0.0", - "once": "^1.4.0", - "request": "^2.88.2", - "retry": "^0.12.0", - "safe-buffer": "^5.2.1", - "semver": "2 >=2.2.1 || 3.x || 4 || 5 || 7", - "slide": "^1.1.6", - "ssri": "^8.0.0" - }, - "optionalDependencies": { - "npmlog": "2 || ^3.1.0 || ^4.0.0" - } - }, - "node_modules/@qiwi/npm-registry-client/node_modules/builtins": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", - "dev": true - }, - "node_modules/@qiwi/npm-registry-client/node_modules/npm-package-arg": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", - "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "semver": "^7.3.4", - "validate-npm-package-name": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@qiwi/npm-registry-client/node_modules/validate-npm-package-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", - "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", - "dev": true, - "dependencies": { - "builtins": "^1.0.3" - } - }, - "node_modules/@rgrove/parse-xml": { - "version": "4.1.0", - "license": "ISC", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@rollup/plugin-commonjs": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.0.tgz", - "integrity": "sha512-BJcu+a+Mpq476DMXG+hevgPSl56bkUoi88dKT8t3RyUp8kGuOh+2bU8Gs7zXDlu+fyZggnJ+iOBGrb/O1SorYg==", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "fdir": "^6.1.1", - "is-reference": "1.2.1", - "magic-string": "^0.30.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=16.0.0 || 14 >= 14.17" - }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-commonjs/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@rollup/plugin-json": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", - "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", - "dependencies": { - "@rollup/pluginutils": "^5.1.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz", - "integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-terser": { - "version": "0.4.4", - "dev": true, - "license": "MIT", - "dependencies": { - "serialize-javascript": "^6.0.1", - "smob": "^1.0.0", - "terser": "^5.17.4" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-virtual": { - "version": "3.0.2", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils": { - "version": "5.1.0", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sindresorhus/slugify": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/transliterate": "^0.1.1", - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sindresorhus/slugify/node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sindresorhus/transliterate": { - "version": "0.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0", - "lodash.deburr": "^4.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sindresorhus/transliterate/node_modules/escape-string-regexp": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "license": "MIT" - }, - "node_modules/@types/accepts": { - "version": "1.3.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/babel__code-frame": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/babel__code-frame/-/babel__code-frame-7.0.6.tgz", - "integrity": "sha512-Anitqkl3+KrzcW2k77lRlg/GfLZLWXBuNgbEcIOU6M92yw42vsd3xV/Z/yAHEj8m+KUjL6bWOVOFqX8PFPJ4LA==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.5", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/better-sqlite3": { - "version": "7.6.11", - "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.11.tgz", - "integrity": "sha512-i8KcD3PgGtGBLl3+mMYA8PdKkButvPyARxA7IQAd6qeslht13qxb1zzO8dRCtE7U3IoJS782zDBAeoKiM695kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/caseless": { - "version": "0.12.5", - "license": "MIT" - }, - "node_modules/@types/chai": { - "version": "4.3.16", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.16.tgz", - "integrity": "sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==", - "dev": true - }, - "node_modules/@types/co-body": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@types/co-body/-/co-body-6.1.3.tgz", - "integrity": "sha512-UhuhrQ5hclX6UJctv5m4Rfp52AfG9o9+d9/HwjxhVB5NjXxr5t9oKgJxN8xRHgr35oo8meUEHUPFWiKg6y71aA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*" - } - }, - "node_modules/@types/command-line-args": { - "version": "5.2.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/content-disposition": { - "version": "0.5.8", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/convert-source-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/convert-source-map/-/convert-source-map-2.0.3.tgz", - "integrity": "sha512-ag0BfJLZf6CQz8VIuRIEYQ5Ggwk/82uvTQf27RcpyDNbY0Vw49LIPqAxk5tqYfrCs9xDaIMvl4aj7ZopnYL8bA==", - "dev": true - }, - "node_modules/@types/cookies": { - "version": "0.9.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/express": "*", - "@types/keygrip": "*", - "@types/node": "*" - } - }, - "node_modules/@types/cors": { - "version": "2.8.17", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/css-font-loading-module": { - "version": "0.0.12", - "license": "MIT" - }, - "node_modules/@types/debounce": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/debounce/-/debounce-1.2.4.tgz", - "integrity": "sha512-jBqiORIzKDOToaF63Fm//haOCHuwQuLa2202RK4MozpA6lh93eCBc+/8+wZn5OzjJt3ySdc+74SXWXB55Ewtyw==", - "dev": true - }, - "node_modules/@types/earcut": { - "version": "2.1.4", - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "license": "MIT" - }, - "node_modules/@types/express": { - "version": "4.17.21", - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.0", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/gapi": { - "version": "0.0.47", - "resolved": "https://registry.npmjs.org/@types/gapi/-/gapi-0.0.47.tgz", - "integrity": "sha512-/ZsLuq6BffMgbKMtZyDZ8vwQvTyKhKQ1G2K6VyWCgtHHhfSSXbk4+4JwImZiTjWNXfI2q1ZStAwFFHSkNoTkHA==" - }, - "node_modules/@types/gapi.drive": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@types/gapi.drive/-/gapi.drive-0.0.9.tgz", - "integrity": "sha512-rnghODv+qpNm3qmb0AQckxfk15MncsuDClqPynoBphgDDmTNj6bC3Sax1GvvTvuYA+lCLtFSZNwRhgiUsIyKQw==", - "dependencies": { - "@types/gapi": "*" - } - }, - "node_modules/@types/google.picker": { - "version": "0.0.42", - "resolved": "https://registry.npmjs.org/@types/google.picker/-/google.picker-0.0.42.tgz", - "integrity": "sha512-7Ut1zDLCGNhyN+0fuIcncpBP9eUsIjLKz6qmVKvdkBUi1EzAskxTcIZcU/w2cO1ens/hEXlqeLd5qAKs/Kqqyw==" - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-assert": { - "version": "1.5.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "license": "MIT" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.6", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/keygrip": { - "version": "1.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/koa": { - "version": "2.15.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/accepts": "*", - "@types/content-disposition": "*", - "@types/cookies": "*", - "@types/http-assert": "*", - "@types/http-errors": "*", - "@types/keygrip": "*", - "@types/koa-compose": "*", - "@types/node": "*" - } - }, - "node_modules/@types/koa-compose": { - "version": "3.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/koa": "*" - } - }, - "node_modules/@types/linkify-it": { - "version": "5.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/lodash": { - "version": "4.17.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/long": { - "version": "4.0.2", - "license": "MIT" - }, - "node_modules/@types/markdown-it": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", - "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", - "dev": true, - "dependencies": { - "@types/linkify-it": "^5", - "@types/mdurl": "^2" - } - }, - "node_modules/@types/mdurl": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "license": "MIT" - }, - "node_modules/@types/minimatch": { - "version": "3.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mocha": { - "version": "10.0.8", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.8.tgz", - "integrity": "sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw==", - "dev": true - }, - "node_modules/@types/node": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.0.0.tgz", - "integrity": "sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==", - "dependencies": { - "undici-types": "~6.11.1" - } - }, - "node_modules/@types/node/node_modules/undici-types": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.11.1.tgz", - "integrity": "sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==" - }, - "node_modules/@types/parse5": { - "version": "6.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/prettier": { - "version": "3.0.0", - "deprecated": "This is a stub types definition. prettier provides its own type definitions, so you do not need this installed.", - "dev": true, - "license": "MIT", - "dependencies": { - "prettier": "*" - } - }, - "node_modules/@types/qs": { - "version": "6.9.14", - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "license": "MIT" - }, - "node_modules/@types/request": { - "version": "2.48.12", - "license": "MIT", - "dependencies": { - "@types/caseless": "*", - "@types/node": "*", - "@types/tough-cookie": "*", - "form-data": "^2.5.0" - } - }, - "node_modules/@types/request/node_modules/form-data": { - "version": "2.5.1", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "license": "MIT" - }, - "node_modules/@types/semver": { - "version": "7.5.8", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/send": { - "version": "0.17.4", - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-handler": { - "version": "6.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "license": "MIT" - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" - }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ws": { - "version": "7.4.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.32", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", - "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "dev": true, - "license": "ISC" - }, - "node_modules/@vitest/expect": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.1.tgz", - "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", - "dev": true, - "dependencies": { - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", - "chai": "^5.1.1", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.1.tgz", - "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", - "dev": true, - "dependencies": { - "@vitest/spy": "^2.1.0-beta.1", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.11" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/spy": "2.1.1", - "msw": "^2.3.5", - "vite": "^5.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/mocker/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/@vitest/pretty-format": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", - "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", - "dev": true, - "dependencies": { - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.1.tgz", - "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", - "dev": true, - "dependencies": { - "@vitest/utils": "2.1.1", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.1.tgz", - "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", - "dev": true, - "dependencies": { - "@vitest/pretty-format": "2.1.1", - "magic-string": "^0.30.11", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.1.tgz", - "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", - "dev": true, - "dependencies": { - "tinyspy": "^3.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.1.tgz", - "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", - "dev": true, - "dependencies": { - "@vitest/pretty-format": "2.1.1", - "loupe": "^3.1.1", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@web/browser-logs": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@web/browser-logs/-/browser-logs-0.4.0.tgz", - "integrity": "sha512-/EBiDAUCJ2DzZhaFxTPRIznEPeafdLbXShIL6aTu7x73x7ZoxSDv7DGuTsh2rWNMUa4+AKli4UORrpyv6QBOiA==", - "dev": true, - "dependencies": { - "errorstacks": "^2.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/config-loader": { - "version": "0.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/dev-server": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/@web/dev-server/-/dev-server-0.4.6.tgz", - "integrity": "sha512-jj/1bcElAy5EZet8m2CcUdzxT+CRvUjIXGh8Lt7vxtthkN9PzY9wlhWx/9WOs5iwlnG1oj0VGo6f/zvbPO0s9w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.11", - "@types/command-line-args": "^5.0.0", - "@web/config-loader": "^0.3.0", - "@web/dev-server-core": "^0.7.2", - "@web/dev-server-rollup": "^0.6.1", - "camelcase": "^6.2.0", - "command-line-args": "^5.1.1", - "command-line-usage": "^7.0.1", - "debounce": "^1.2.0", - "deepmerge": "^4.2.2", - "internal-ip": "^6.2.0", - "nanocolors": "^0.2.1", - "open": "^8.0.2", - "portfinder": "^1.0.32" - }, - "bin": { - "wds": "dist/bin.js", - "web-dev-server": "dist/bin.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/dev-server-core": { - "version": "0.7.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/koa": "^2.11.6", - "@types/ws": "^7.4.0", - "@web/parse5-utils": "^2.1.0", - "chokidar": "^3.4.3", - "clone": "^2.1.2", - "es-module-lexer": "^1.0.0", - "get-stream": "^6.0.0", - "is-stream": "^2.0.0", - "isbinaryfile": "^5.0.0", - "koa": "^2.13.0", - "koa-etag": "^4.0.0", - "koa-send": "^5.0.1", - "koa-static": "^5.0.0", - "lru-cache": "^8.0.4", - "mime-types": "^2.1.27", - "parse5": "^6.0.1", - "picomatch": "^2.2.2", - "ws": "^7.4.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/dev-server-core/node_modules/clone": { - "version": "2.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/@web/dev-server-core/node_modules/is-stream": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@web/dev-server-core/node_modules/lru-cache": { - "version": "8.0.5", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16.14" - } - }, - "node_modules/@web/dev-server-core/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@web/dev-server-core/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@web/dev-server-esbuild": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@web/dev-server-esbuild/-/dev-server-esbuild-1.0.2.tgz", - "integrity": "sha512-ak5mKt7L0H/Fa470Ku7p9A1eI32DNyFGM83jDkJviBO8r3lM00O5hVFW1K+UIYNC5EyanLyPxTqgtIuQEyMYcQ==", - "dev": true, - "dependencies": { - "@mdn/browser-compat-data": "^4.0.0", - "@web/dev-server-core": "^0.7.0", - "esbuild": "^0.19.11", - "get-tsconfig": "^4.7.2", - "parse5": "^6.0.1", - "ua-parser-js": "^1.0.33" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/dev-server-esbuild/node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@web/dev-server-esbuild/node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" - } - }, - "node_modules/@web/dev-server-rollup": { - "version": "0.6.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/plugin-node-resolve": "^15.0.1", - "@web/dev-server-core": "^0.7.0", - "nanocolors": "^0.2.1", - "parse5": "^6.0.1", - "rollup": "^4.4.0", - "whatwg-url": "^11.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/dev-server/node_modules/camelcase": { - "version": "6.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@web/parse5-utils": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/parse5": "^6.0.1", - "parse5": "^6.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/test-runner": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@web/test-runner/-/test-runner-0.19.0.tgz", - "integrity": "sha512-qLUupi88OK1Kl52cWPD/2JewUCRUxYsZ1V1DyLd05P7u09zCdrUYrtkB/cViWyxlBe/TOvqkSNpcTv6zLJ9GoA==", - "dev": true, - "dependencies": { - "@web/browser-logs": "^0.4.0", - "@web/config-loader": "^0.3.0", - "@web/dev-server": "^0.4.0", - "@web/test-runner-chrome": "^0.17.0", - "@web/test-runner-commands": "^0.9.0", - "@web/test-runner-core": "^0.13.0", - "@web/test-runner-mocha": "^0.9.0", - "camelcase": "^6.2.0", - "command-line-args": "^5.1.1", - "command-line-usage": "^7.0.1", - "convert-source-map": "^2.0.0", - "diff": "^5.0.0", - "globby": "^11.0.1", - "nanocolors": "^0.2.1", - "portfinder": "^1.0.32", - "source-map": "^0.7.3" - }, - "bin": { - "web-test-runner": "dist/bin.js", - "wtr": "dist/bin.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/test-runner-chrome": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@web/test-runner-chrome/-/test-runner-chrome-0.17.0.tgz", - "integrity": "sha512-Il5N9z41NKWCrQM1TVgRaDWWYoJtG5Ha4fG+cN1MWL2OlzBS4WoOb4lFV3EylZ7+W3twZOFr1zy2Rx61yDYd/A==", - "dev": true, - "dependencies": { - "@web/test-runner-core": "^0.13.0", - "@web/test-runner-coverage-v8": "^0.8.0", - "async-mutex": "0.4.0", - "chrome-launcher": "^0.15.0", - "puppeteer-core": "^23.2.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/test-runner-commands": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@web/test-runner-commands/-/test-runner-commands-0.9.0.tgz", - "integrity": "sha512-zeLI6QdH0jzzJMDV5O42Pd8WLJtYqovgdt0JdytgHc0d1EpzXDsc7NTCJSImboc2NcayIsWAvvGGeRF69SMMYg==", - "dev": true, - "dependencies": { - "@web/test-runner-core": "^0.13.0", - "mkdirp": "^1.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/test-runner-core": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/@web/test-runner-core/-/test-runner-core-0.13.3.tgz", - "integrity": "sha512-ilDqF/v2sj0sD69FNSIDT7uw4M1yTVedLBt32/lXy3MMi6suCM7m/ZlhsBy8PXhf879WMvzBOl/vhJBpEMB9vA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.11", - "@types/babel__code-frame": "^7.0.2", - "@types/co-body": "^6.1.0", - "@types/convert-source-map": "^2.0.0", - "@types/debounce": "^1.2.0", - "@types/istanbul-lib-coverage": "^2.0.3", - "@types/istanbul-reports": "^3.0.0", - "@web/browser-logs": "^0.4.0", - "@web/dev-server-core": "^0.7.2", - "chokidar": "^3.4.3", - "cli-cursor": "^3.1.0", - "co-body": "^6.1.0", - "convert-source-map": "^2.0.0", - "debounce": "^1.2.0", - "dependency-graph": "^0.11.0", - "globby": "^11.0.1", - "internal-ip": "^6.2.0", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.0.2", - "log-update": "^4.0.0", - "nanocolors": "^0.2.1", - "nanoid": "^3.1.25", - "open": "^8.0.2", - "picomatch": "^2.2.2", - "source-map": "^0.7.3" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/test-runner-core/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@web/test-runner-core/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@web/test-runner-core/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@web/test-runner-core/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@web/test-runner-core/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@web/test-runner-core/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@web/test-runner-coverage-v8": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@web/test-runner-coverage-v8/-/test-runner-coverage-v8-0.8.0.tgz", - "integrity": "sha512-PskiucYpjUtgNfR2zF2AWqWwjXL7H3WW/SnCAYmzUrtob7X9o/+BjdyZ4wKbOxWWSbJO4lEdGIDLu+8X2Xw+lA==", - "dev": true, - "dependencies": { - "@web/test-runner-core": "^0.13.0", - "istanbul-lib-coverage": "^3.0.0", - "lru-cache": "^8.0.4", - "picomatch": "^2.2.2", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/test-runner-coverage-v8/node_modules/lru-cache": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", - "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", - "dev": true, - "engines": { - "node": ">=16.14" - } - }, - "node_modules/@web/test-runner-coverage-v8/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@web/test-runner-mocha": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@web/test-runner-mocha/-/test-runner-mocha-0.9.0.tgz", - "integrity": "sha512-ZL9F6FXd0DBQvo/h/+mSfzFTSRVxzV9st/AHhpgABtUtV/AIpVE9to6+xdkpu6827kwjezdpuadPfg+PlrBWqQ==", - "dev": true, - "dependencies": { - "@web/test-runner-core": "^0.13.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@web/test-runner/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@web/test-runner/node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/@web/test-runner/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@webgpu/types": { - "version": "0.1.40", - "license": "BSD-3-Clause" - }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@zeit/schemas": { - "version": "2.36.0", - "license": "MIT" - }, - "node_modules/a-sync-waterfall": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.11.3", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "peer": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.1", - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/aggregate-error": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/node_modules/ansi-regex": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "license": "MIT" - }, - "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "6.0.1", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.1", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ansicolors": { - "version": "0.3.2", - "dev": true, - "license": "MIT" - }, - "node_modules/any-promise": { - "version": "0.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true, - "optional": true - }, - "node_modules/arch": { - "version": "2.2.0", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "deprecated": "This package is no longer supported.", - "dev": true, - "optional": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/are-we-there-yet/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "optional": true - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/are-we-there-yet/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "optional": true - }, - "node_modules/are-we-there-yet/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "license": "MIT" - }, - "node_modules/argparse": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-back": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-differ": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/array-find-index": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/array-includes": { - "version": "3.1.8", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrgv": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/arrify": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-never": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.2.1.tgz", - "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==", - "dev": true - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.5", - "dev": true, - "license": "MIT" - }, - "node_modules/async-mutex": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.4.0.tgz", - "integrity": "sha512-eJFZ1YhRR8UN8eBLoNzcDPcy/jqjsg6I1AP+KvWQX80BqOSW1oJPJXDylPUEeMr2ZQvHgnQ//Lp6f3RQ1zI7HA==", - "dev": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/async-retry": { - "version": "1.3.3", - "license": "MIT", - "optional": true, - "dependencies": { - "retry": "0.13.1" - } - }, - "node_modules/async-retry/node_modules/retry": { - "version": "0.13.1", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "license": "MIT" - }, - "node_modules/ava": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.8.2", - "acorn-walk": "^8.2.0", - "ansi-styles": "^6.2.1", - "arrgv": "^1.0.2", - "arrify": "^3.0.0", - "callsites": "^4.0.0", - "cbor": "^8.1.0", - "chalk": "^5.2.0", - "chokidar": "^3.5.3", - "chunkd": "^2.0.1", - "ci-info": "^3.8.0", - "ci-parallel-vars": "^1.0.1", - "clean-yaml-object": "^0.1.0", - "cli-truncate": "^3.1.0", - "code-excerpt": "^4.0.0", - "common-path-prefix": "^3.0.0", - "concordance": "^5.0.4", - "currently-unhandled": "^0.4.1", - "debug": "^4.3.4", - "emittery": "^1.0.1", - "figures": "^5.0.0", - "globby": "^13.1.4", - "ignore-by-default": "^2.1.0", - "indent-string": "^5.0.0", - "is-error": "^2.2.2", - "is-plain-object": "^5.0.0", - "is-promise": "^4.0.0", - "matcher": "^5.0.0", - "mem": "^9.0.2", - "ms": "^2.1.3", - "p-event": "^5.0.1", - "p-map": "^5.5.0", - "picomatch": "^2.3.1", - "pkg-conf": "^4.0.0", - "plur": "^5.1.0", - "pretty-ms": "^8.0.0", - "resolve-cwd": "^3.0.0", - "stack-utils": "^2.0.6", - "strip-ansi": "^7.0.1", - "supertap": "^3.0.1", - "temp-dir": "^3.0.0", - "write-file-atomic": "^5.0.1", - "yargs": "^17.7.2" - }, - "bin": { - "ava": "entrypoints/cli.mjs" - }, - "engines": { - "node": ">=14.19 <15 || >=16.15 <17 || >=18" - }, - "peerDependencies": { - "@ava/typescript": "*" - }, - "peerDependenciesMeta": { - "@ava/typescript": { - "optional": true - } - } - }, - "node_modules/ava/node_modules/chalk": { - "version": "5.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ava/node_modules/globby": { - "version": "13.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ava/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/ava/node_modules/slash": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz", - "integrity": "sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA==", - "dev": true - }, - "node_modules/b4a": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", - "dev": true - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-jest/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/babel-jest/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/babel-jest/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-jest/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-walk": { - "version": "3.0.0-canary-5", - "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", - "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.9.6" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/bare-events": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", - "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", - "dev": true, - "optional": true - }, - "node_modules/bare-fs": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.3.tgz", - "integrity": "sha512-7RYKL+vZVCyAsMLi5SPu7QGauGGT8avnP/HO571ndEuV4MYdGXvLhtW67FuLPeEI8EiIY7zbbRR9x7x7HU0kgw==", - "dev": true, - "optional": true, - "dependencies": { - "bare-events": "^2.0.0", - "bare-path": "^2.0.0", - "bare-stream": "^2.0.0" - } - }, - "node_modules/bare-os": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.2.tgz", - "integrity": "sha512-HZoJwzC+rZ9lqEemTMiO0luOePoGYNBgsLLgegKR/cljiJvcDNhDZQkzC+NC5Oh0aHbdBNSOHpghwMuB5tqhjg==", - "dev": true, - "optional": true - }, - "node_modules/bare-path": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", - "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", - "dev": true, - "optional": true, - "dependencies": { - "bare-os": "^2.1.0" - } - }, - "node_modules/bare-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.2.1.tgz", - "integrity": "sha512-YTB47kHwBW9zSG8LD77MIBAAQXjU2WjAkMHeeb7hUplVs6+IoM5I7uEVQNPMB7lj9r8I76UMdoMkGnCodHOLqg==", - "dev": true, - "optional": true, - "dependencies": { - "b4a": "^1.6.6", - "streamx": "^2.18.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/basic-ftp": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", - "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/bcp-47": { - "version": "1.0.8", - "dev": true, - "license": "MIT", - "dependencies": { - "is-alphabetical": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/bcp-47-match": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/bcp-47-normalize": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "bcp-47": "^1.0.0", - "bcp-47-match": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/better-path-resolve": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz", - "integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==", - "dev": true, - "dependencies": { - "is-windows": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/better-sqlite3": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.3.0.tgz", - "integrity": "sha512-iHt9j8NPYF3oKCNOO5ZI4JwThjt3Z6J6XrcwG85VNMVzv1ByqrHWv5VILEbCMFWDsoHhXvQ7oC8vgRXFAKgl9w==", - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.5.0", - "prebuild-install": "^7.1.1" - } - }, - "node_modules/bignumber.js": { - "version": "9.1.2", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "license": "MIT", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/blueimp-md5": { - "version": "2.19.0", - "dev": true, - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/boxen": { - "version": "7.0.0", - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^7.0.0", - "chalk": "^5.0.1", - "cli-boxes": "^3.0.0", - "string-width": "^5.1.2", - "type-fest": "^2.13.0", - "widest-line": "^4.0.1", - "wrap-ansi": "^8.0.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/camelcase": { - "version": "7.0.1", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/chalk": { - "version": "5.3.0", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/boxen/node_modules/type-fest": { - "version": "2.19.0", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.0", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "license": "BSD-3-Clause" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "devOptional": true, - "license": "MIT" - }, - "node_modules/builtins": { - "version": "5.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/bytes": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/c8": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.2.tgz", - "integrity": "sha512-Qr6rj76eSshu5CgRYvktW0uM0CFY0yi4Fd5D0duDXO6sYinyopmftUiJVuzBQxQcwQLor7JWDVRP+dUfCmzgJw==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^3.1.1", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.1.6", - "test-exclude": "^7.0.1", - "v8-to-istanbul": "^9.0.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "monocart-coverage-reports": "^2" - }, - "peerDependenciesMeta": { - "monocart-coverage-reports": { - "optional": true - } - } - }, - "node_modules/c8/node_modules/find-up": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/c8/node_modules/locate-path": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/c8/node_modules/p-limit": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/c8/node_modules/p-locate": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/c8/node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cache-content-type": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "^2.1.18", - "ylru": "^1.2.0" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/cachedir": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", - "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" - }, - "node_modules/callsites": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001607", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0", - "peer": true - }, - "node_modules/cardinal": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansicolors": "~0.3.2", - "redeyed": "~2.1.0" - }, - "bin": { - "cdl": "bin/cdl.js" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true - }, - "node_modules/cbor": { - "version": "8.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "nofilter": "^3.1.0" - }, - "engines": { - "node": ">=12.19" - } - }, - "node_modules/chai": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", - "dev": true, - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk-template": { - "version": "0.4.0", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/chalk-template?sponsor=1" - } - }, - "node_modules/chalk-template/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/chalk-template/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk-template/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/chalk-template/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/color-convert": { - "version": "1.9.3", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/chalk/node_modules/color-name": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/character-parser": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-regex": "^1.0.3" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/charm": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/charm/-/charm-1.0.2.tgz", - "integrity": "sha512-wqW3VdPnlSWT4eRiYX+hcs+C6ViBPUWk1qTCd+37qw9kEm/a5n2qcyQDMBWvSYKN/ctqZzeXNQaeBjOetJJUkw==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1" - } - }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "engines": { - "node": ">= 16" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-launcher": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", - "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0" - }, - "bin": { - "print-chrome-path": "bin/print-chrome-path.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/chrome-launcher/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chromium-bidi": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.5.tgz", - "integrity": "sha512-RuLrmzYrxSb0s9SgpB+QN5jJucPduZQ/9SIe76MDxYJuecPW5mxMdacJ1f4EtgiV+R0p3sCkznTMvH0MPGFqjA==", - "dev": true, - "dependencies": { - "mitt": "3.0.1", - "urlpattern-polyfill": "10.0.0", - "zod": "3.23.8" - }, - "peerDependencies": { - "devtools-protocol": "*" - } - }, - "node_modules/chunkd": { - "version": "2.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/ci-info": { - "version": "3.9.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ci-parallel-vars": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/clean-stack": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clean-yaml-object": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-cursor": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-table3": { - "version": "0.6.4", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-table3/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/cli-table3/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clipboardy": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "arch": "^2.2.0", - "execa": "^5.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clipboardy/node_modules/execa": { - "version": "5.1.1", - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/clipboardy/node_modules/human-signals": { - "version": "2.1.0", - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/clipboardy/node_modules/is-stream": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clipboardy/node_modules/mimic-fn": { - "version": "2.1.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/clipboardy/node_modules/npm-run-path": { - "version": "4.0.1", - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/clipboardy/node_modules/onetime": { - "version": "5.1.2", - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clipboardy/node_modules/strip-final-newline": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "license": "MIT" - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/co": { - "version": "4.6.0", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/co-body": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.2.0.tgz", - "integrity": "sha512-Kbpv2Yd1NdL1V/V4cwLVxraHDV6K8ayohr2rmH0J87Er8+zJjcTa6dAn9QMPC9CRgU8+aNajKbSf1TzDB1yKPA==", - "dev": true, - "dependencies": { - "@hapi/bourne": "^3.0.0", - "inflation": "^2.0.0", - "qs": "^6.5.2", - "raw-body": "^2.3.3", - "type-is": "^1.6.16" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/code-excerpt": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "convert-to-spaces": "^2.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/codemirror": { - "version": "6.0.1", - "license": "MIT", - "dependencies": { - "@codemirror/autocomplete": "^6.0.0", - "@codemirror/commands": "^6.0.0", - "@codemirror/language": "^6.0.0", - "@codemirror/lint": "^6.0.0", - "@codemirror/search": "^6.0.0", - "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/command-line-args": { - "version": "5.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/command-line-usage": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "array-back": "^6.2.2", - "chalk-template": "^0.4.0", - "table-layout": "^3.0.0", - "typical": "^7.1.1" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "6.2.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.17" - } - }, - "node_modules/command-line-usage/node_modules/typical": { - "version": "7.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.17" - } - }, - "node_modules/commander": { - "version": "12.1.0", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/commondir": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/compressible": { - "version": "2.0.18", - "license": "MIT", - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "license": "MIT" - }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "engines": [ - "node >= 6.0" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concordance": { - "version": "5.0.4", - "dev": true, - "license": "ISC", - "dependencies": { - "date-time": "^3.1.0", - "esutils": "^2.0.3", - "fast-diff": "^1.2.0", - "js-string-escape": "^1.0.1", - "lodash": "^4.17.15", - "md5-hex": "^3.0.1", - "semver": "^7.3.2", - "well-known-symbols": "^2.0.0" - }, - "engines": { - "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true, - "optional": true - }, - "node_modules/constantinople": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.6.0", - "@babel/types": "^7.6.1" - } - }, - "node_modules/content-disposition": { - "version": "0.5.2", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/convert-to-spaces": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/cookie": { - "version": "0.6.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "license": "MIT" - }, - "node_modules/cookies": { - "version": "0.9.1", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "keygrip": "~1.1.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true - }, - "node_modules/cors": { - "version": "2.8.5", - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cosmiconfig": { - "version": "9.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/create-jest": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/create-jest/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/create-jest/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/create-jest/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/crelt": { - "version": "1.0.6", - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssstyle": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", - "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", - "dev": true, - "dependencies": { - "rrweb-cssom": "^0.7.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/currently-unhandled": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "array-find-index": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", - "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/data-urls": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/data-urls/node_modules/punycode": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/data-urls/node_modules/tr46": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/data-urls/node_modules/whatwg-url": { - "version": "14.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "^5.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/date-time": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "time-zone": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/debounce": { - "version": "1.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js": { - "version": "10.4.3", - "dev": true, - "license": "MIT" - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/dedent": { - "version": "1.5.1", - "dev": true, - "license": "MIT", - "peer": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-equal": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/default-gateway/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-gateway/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/default-gateway/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/default-gateway/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/default-gateway/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, - "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/depd": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dependency-graph": { - "version": "0.11.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dev-ip": { - "version": "1.0.1", - "dev": true, - "bin": { - "dev-ip": "lib/dev-ip.js" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/devtools-protocol": { - "version": "0.0.1330662", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1330662.tgz", - "integrity": "sha512-pzh6YQ8zZfz3iKlCvgzVCu22NdpZ8hNmwU6WnQjNVquh0A9iVosPtNLWDwaWVGyrntQlltPFztTMK5Cg6lfCuw==", - "dev": true - }, - "node_modules/diff": { - "version": "4.0.2", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/doctypes": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", - "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==", - "dev": true - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/dotenv": { - "version": "16.4.5", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/duplexify": { - "version": "4.1.3", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.2" - } - }, - "node_modules/earcut": { - "version": "2.2.4", - "license": "ISC" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "license": "MIT" - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/effect": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/effect/-/effect-3.6.5.tgz", - "integrity": "sha512-NhopZTAKljaAlR0CEroOAJJngdqg7bzlnWcDrCwh4d2WNVohVbBtUS4SGqLt8tUy7IFsTWATYiUtmhDG+YELjA==", - "dev": true - }, - "node_modules/ejs": { - "version": "3.1.10", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.730", - "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/eleventy-plugin-youtube-embed": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/eleventy-plugin-youtube-embed/-/eleventy-plugin-youtube-embed-1.11.0.tgz", - "integrity": "sha512-02HRfQqE7LtD3HQlt+EhvKi4umvFBWppJEFwTfr/EC7kV/aIiLegAMoDlH+atK4KoZu6vcLJvCrciCa9IwJ7dQ==", - "dependencies": { - "@11ty/eleventy-fetch": "^4.0.1", - "deepmerge": "^4.3.1", - "lite-youtube-embed": "^0.3.3", - "string-replace-async": "^3.0.2" - } - }, - "node_modules/emittery": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "license": "MIT" - }, - "node_modules/emojilib": { - "version": "2.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/encoding": { - "version": "0.1.13", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enquirer": { - "version": "2.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/enquirer/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/enquirer/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ent": { - "version": "2.2.0", - "license": "MIT", - "optional": true - }, - "node_modules/entities": { - "version": "4.5.0", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/errno": { - "version": "0.1.8", - "dev": true, - "license": "MIT", - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/errorstacks": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/errorstacks/-/errorstacks-2.4.1.tgz", - "integrity": "sha512-jE4i0SMYevwu/xxAuzhly/KTwtj0xDhbzB6m1xPImxTkw8wcCbgarOQPfCVMi5JKVyW7in29pNJCCJrry3Ynnw==", - "dev": true - }, - "node_modules/es-abstract": { - "version": "1.23.3", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.5.0", - "dev": true, - "license": "MIT" - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", - "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.0", - "@esbuild/android-arm": "0.24.0", - "@esbuild/android-arm64": "0.24.0", - "@esbuild/android-x64": "0.24.0", - "@esbuild/darwin-arm64": "0.24.0", - "@esbuild/darwin-x64": "0.24.0", - "@esbuild/freebsd-arm64": "0.24.0", - "@esbuild/freebsd-x64": "0.24.0", - "@esbuild/linux-arm": "0.24.0", - "@esbuild/linux-arm64": "0.24.0", - "@esbuild/linux-ia32": "0.24.0", - "@esbuild/linux-loong64": "0.24.0", - "@esbuild/linux-mips64el": "0.24.0", - "@esbuild/linux-ppc64": "0.24.0", - "@esbuild/linux-riscv64": "0.24.0", - "@esbuild/linux-s390x": "0.24.0", - "@esbuild/linux-x64": "0.24.0", - "@esbuild/netbsd-x64": "0.24.0", - "@esbuild/openbsd-arm64": "0.24.0", - "@esbuild/openbsd-x64": "0.24.0", - "@esbuild/sunos-x64": "0.24.0", - "@esbuild/win32-arm64": "0.24.0", - "@esbuild/win32-ia32": "0.24.0", - "@esbuild/win32-x64": "0.24.0" - } - }, - "node_modules/esbuild/node_modules/@esbuild/aix-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", - "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/android-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", - "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/android-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", - "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/android-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", - "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/darwin-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", - "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", - "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", - "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", - "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", - "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", - "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-loong64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", - "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", - "cpu": [ - "loong64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", - "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", - "cpu": [ - "mips64el" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", - "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", - "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", - "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/linux-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", - "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", - "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", - "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", - "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", - "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", - "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/esbuild/node_modules/@esbuild/win32-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", - "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.1", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-expect-type": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-expect-type/-/eslint-plugin-expect-type-0.4.3.tgz", - "integrity": "sha512-frRGE4Qg5jFJgY11xRvK3iZu/gDnn83d1a5iPelSotIJw/JhuhqZ9bjE2fRD6nV7Aof9E+SHzNGOMWngB3wbTw==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^6.10.0 || ^7.0.1 || ^8", - "fs-extra": "^11.1.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@typescript-eslint/parser": ">=6", - "eslint": ">=7", - "typescript": ">=4" - } - }, - "node_modules/eslint-plugin-expect-type/node_modules/fs-extra": { - "version": "11.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/eslint-plugin-expect-type/node_modules/jsonfile": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/eslint-plugin-expect-type/node_modules/universalify": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/esm-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz", - "integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/espree": { - "version": "9.6.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "license": "MIT" - }, - "node_modules/esutils": { - "version": "2.0.3", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "license": "MIT" - }, - "node_modules/execa": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "license": "(MIT OR WTFPL)", - "engines": { - "node": ">=6" - } - }, - "node_modules/expect": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/content-disposition": { - "version": "0.5.4", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", - "license": "MIT" - }, - "node_modules/express/node_modules/range-parser": { - "version": "1.2.1", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "license": "MIT" - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extendable-error": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz", - "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==", - "dev": true - }, - "node_modules/external-editor": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/farmhash-modern": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/farmhash-modern/-/farmhash-modern-1.1.0.tgz", - "integrity": "sha512-6ypT4XfgqJk/F3Yuv4SX26I3doUjt0GTG4a+JgWxXQpxXzTBq8fPUeGHfcYMMDPHJHm3yPOSjaeBwBGAHWXCdA==", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/fast-check": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.21.0.tgz", - "integrity": "sha512-QpmbiqRFRZ+SIlBJh6xi5d/PgXciUc/xWKc4Vi2RWEHHIRx6oM3f0fWNna++zP9VB5HUBTObUK9gTKQP3vVcrQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "dependencies": { - "pure-rand": "^6.1.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "license": "MIT" - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" - }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "license": "MIT", - "dependencies": { - "punycode": "^1.3.2" - } - }, - "node_modules/fast-xml-parser": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", - "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - } - ], - "optional": true, - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "license": "Apache-2.0", - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/fdir": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.3.0.tgz", - "integrity": "sha512-QOnuT+BOtivR77wYvCWHfGt9s4Pz1VIMbD463vegT5MLqNXy8rYFT/lPVEqf/bhYeT6qmqrNHhsX+rWwe3rOCQ==", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fflate": { - "version": "0.8.2", - "dev": true, - "license": "MIT" - }, - "node_modules/figures": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^5.0.0", - "is-unicode-supported": "^1.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "license": "MIT" - }, - "node_modules/filelist": { - "version": "1.0.4", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/find-replace": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-back": "^3.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/firebase-admin": { - "version": "12.5.0", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-12.5.0.tgz", - "integrity": "sha512-ad8vnlPcuuZN9scSgY8UnAxPI4mzP2/Q+dsrVLTf+j3h7bIq0FOelDCDGz4StgKJdk244v2kpOxqJjPG3grBHg==", - "dependencies": { - "@fastify/busboy": "^3.0.0", - "@firebase/database-compat": "^1.0.2", - "@firebase/database-types": "^1.0.0", - "@types/node": "^22.0.1", - "farmhash-modern": "^1.1.0", - "jsonwebtoken": "^9.0.0", - "jwks-rsa": "^3.1.0", - "node-forge": "^1.3.1", - "uuid": "^10.0.0" - }, - "engines": { - "node": ">=14" - }, - "optionalDependencies": { - "@google-cloud/firestore": "^7.7.0", - "@google-cloud/storage": "^7.7.0" - } - }, - "node_modules/firebase-admin/node_modules/@types/node": { - "version": "22.2.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.2.0.tgz", - "integrity": "sha512-bm6EG6/pCpkxDf/0gDNDdtDILMOHgaQBVOJGdwsqClnxA3xL6jtMv76rLBc006RVMWbmaf0xbmom4Z/5o2nRkQ==", - "dependencies": { - "undici-types": "~6.13.0" - } - }, - "node_modules/firebase-admin/node_modules/undici-types": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", - "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==" - }, - "node_modules/firebase-admin/node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/firebase-functions": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-6.0.1.tgz", - "integrity": "sha512-0rIpTU6dnLRvP3IK+okn1FDjoqjzShm0/S+i4OMY7JFu/HJoyJ1JNkrT4KjECy1/mCHK49KsmH8iYE0rzrglHg==", - "dependencies": { - "@types/cors": "^2.8.5", - "@types/express": "4.17.3", - "cors": "^2.8.5", - "express": "^4.17.1", - "protobufjs": "^7.2.2" - }, - "bin": { - "firebase-functions": "lib/bin/firebase-functions.js" - }, - "engines": { - "node": ">=14.10.0" - }, - "peerDependencies": { - "firebase-admin": "^11.10.0 || ^12.0.0" - } - }, - "node_modules/firebase-functions-test": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/lodash": "^4.14.104", - "lodash": "^4.17.5", - "ts-deepmerge": "^2.0.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "firebase-admin": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0", - "firebase-functions": ">=4.9.0", - "jest": ">=28.0.0" - } - }, - "node_modules/firebase-functions/node_modules/@types/express": { - "version": "4.17.3", - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/serve-static": "*" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/brace-expansion": { - "version": "1.1.11", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/flat-cache/node_modules/glob": { - "version": "7.2.3", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flat-cache/node_modules/minimatch": { - "version": "3.1.2", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "license": "ISC" - }, - "node_modules/for-each": { - "version": "0.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.1.1", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "license": "MIT" - }, - "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/functions": { - "resolved": "packages/node-proxy-server/functions", - "link": true - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "optional": true, - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", - "dev": true, - "optional": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", - "dev": true, - "optional": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "optional": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gaxios": { - "version": "6.4.0", - "license": "Apache-2.0", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.9", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/gaxios/node_modules/is-stream": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gaxios/node_modules/uuid": { - "version": "9.0.1", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/gcp-metadata": { - "version": "6.1.0", - "license": "Apache-2.0", - "dependencies": { - "gaxios": "^6.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.7.5", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/get-uri": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", - "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", - "dev": true, - "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4", - "fs-extra": "^11.2.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/get-uri/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/get-uri/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/get-uri/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "license": "MIT" - }, - "node_modules/github-slugger": { - "version": "1.5.0", - "dev": true, - "license": "ISC" - }, - "node_modules/glob": { - "version": "10.4.1", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/google-auth-library": { - "version": "9.7.0", - "license": "Apache-2.0", - "dependencies": { - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "gaxios": "^6.1.1", - "gcp-metadata": "^6.1.0", - "gtoken": "^7.0.0", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/google-gax": { - "version": "4.3.3", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "~1.10.3", - "@grpc/proto-loader": "^0.7.0", - "@types/long": "^4.0.0", - "abort-controller": "^3.0.0", - "duplexify": "^4.0.0", - "google-auth-library": "^9.3.0", - "node-fetch": "^2.6.1", - "object-hash": "^3.0.0", - "proto3-json-serializer": "^2.0.0", - "protobufjs": "7.2.6", - "retry-request": "^7.0.0", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/google-gax/node_modules/uuid": { - "version": "9.0.1", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "dev": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/gray-matter": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/gtoken": { - "version": "7.1.0", - "license": "MIT", - "dependencies": { - "gaxios": "^6.0.0", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/hamljs": { - "version": "0.6.2", - "dev": true - }, - "node_modules/handlebars": { - "version": "4.7.8", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/har-validator/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/har-validator/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true, - "optional": true - }, - "node_modules/hasown": { - "version": "2.0.2", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-encoding": "^3.1.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/html-entities": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/http-assert": { - "version": "1.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-equal": "~1.0.1", - "http-errors": "~1.8.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-assert/node_modules/depd": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-assert/node_modules/http-errors": { - "version": "1.8.1", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-assert/node_modules/statuses": { - "version": "1.5.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-equiv-refresh": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "license": "MIT" - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/human-id": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/human-id/-/human-id-1.0.2.tgz", - "integrity": "sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==", - "dev": true - }, - "node_modules/human-signals": { - "version": "4.3.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/idb": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/idb/-/idb-8.0.0.tgz", - "integrity": "sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==" - }, - "node_modules/idb-keyval": { - "version": "6.2.1", - "license": "Apache-2.0" - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-by-default": { - "version": "2.1.0", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10 <11 || >=12 <13 || >=14" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inflation": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.1.0.tgz", - "integrity": "sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "node_modules/ini": { - "version": "1.3.8", - "license": "ISC" - }, - "node_modules/innertext": { - "version": "1.0.3", - "dev": true, - "license": "ISC", - "dependencies": { - "html-entities": "^1.2.0" - } - }, - "node_modules/internal-ip": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-6.2.0.tgz", - "integrity": "sha512-D8WGsR6yDt8uq7vDMu7mjcR+yRMm3dW8yufyChmszWRjcSHuxLBkR3GdS2HZAjodsaGuCvXeEJpueisXJULghg==", - "dev": true, - "dependencies": { - "default-gateway": "^6.0.0", - "ipaddr.js": "^1.9.1", - "is-ip": "^3.1.0", - "p-event": "^4.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/internal-ip?sponsor=1" - } - }, - "node_modules/internal-ip/node_modules/p-event": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", - "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", - "dev": true, - "dependencies": { - "p-timeout": "^3.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/internal-ip/node_modules/p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dev": true, - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/ip-address/node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true - }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true - }, - "node_modules/ip-regex": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", - "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/irregular-plurals": { - "version": "3.5.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-alphabetical": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-decimal": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-error": { - "version": "2.2.2", - "dev": true, - "license": "MIT" - }, - "node_modules/is-expression": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^7.1.1", - "object-assign": "^4.1.1" - } - }, - "node_modules/is-expression/node_modules/acorn": { - "version": "7.4.1", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-ip": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz", - "integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==", - "dev": true, - "dependencies": { - "ip-regex": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-json": { - "version": "2.0.1", - "dev": true, - "license": "ISC" - }, - "node_modules/is-module": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-port-reachable": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-promise": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/is-reference": { - "version": "1.2.1", - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-subdir": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-subdir/-/is-subdir-1.2.0.tgz", - "integrity": "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==", - "dev": true, - "dependencies": { - "better-path-resolve": "1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "dev": true, - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/isbinaryfile": { - "version": "5.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "license": "ISC" - }, - "node_modules/ismobilejs": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/iso-639-1": { - "version": "2.1.15", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.2", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jackspeak": { - "version": "3.4.0", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jake": { - "version": "10.8.7", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jake/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jake/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/jake/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jake/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/jake/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jake/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-changed-files/node_modules/execa": { - "version": "5.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/jest-changed-files/node_modules/human-signals": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/jest-changed-files/node_modules/is-stream": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-changed-files/node_modules/mimic-fn": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/jest-changed-files/node_modules/npm-run-path": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-changed-files/node_modules/onetime": { - "version": "5.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-changed-files/node_modules/p-limit": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-changed-files/node_modules/strip-final-newline": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/jest-circus": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-circus/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-circus/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-circus/node_modules/p-limit": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-circus/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-cli": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-cli/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-cli/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-cli/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-cli/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-config": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-config/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-config/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/jest-config/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-config/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-config/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-config/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jest-config/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-diff": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-diff/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-each/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-each/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-each/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-matcher-utils/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-matcher-utils/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-matcher-utils/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-message-util/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-mock": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-resolve/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-resolve/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-resolve/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runner": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-runner/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-runner/node_modules/emittery": { - "version": "0.13.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/jest-runner/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runner/node_modules/p-limit": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-runner/node_modules/source-map-support": { - "version": "0.5.13", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/jest-runner/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-runtime/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/jest-runtime/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-runtime/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-runtime/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jest-runtime/node_modules/strip-bom": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-snapshot/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-snapshot/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-snapshot/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-util": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-util/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-util/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-util/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/jest-util/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-validate": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-validate/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-validate/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-validate/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-watcher/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-watcher/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-watcher/node_modules/emittery": { - "version": "0.13.1", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/jest-watcher/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watcher/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jose": { - "version": "4.15.5", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/js-string-escape": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/js-stringify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", - "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true - }, - "node_modules/jsdom": { - "version": "25.0.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", - "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", - "dev": true, - "dependencies": { - "cssstyle": "^4.1.0", - "data-urls": "^5.0.0", - "decimal.js": "^10.4.3", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.12", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.7.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^5.0.0", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0", - "ws": "^8.18.0", - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "canvas": "^2.11.2" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/parse5": { - "version": "7.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/jsdom/node_modules/punycode": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/jsdom/node_modules/tr46": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/jsdom/node_modules/whatwg-url": { - "version": "14.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "^5.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-bigint": { - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "bignumber.js": "^9.0.0" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "node_modules/json-schema-ref-parser": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", - "integrity": "sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q==", - "deprecated": "Please switch to @apidevtools/json-schema-ref-parser", - "dependencies": { - "@apidevtools/json-schema-ref-parser": "9.0.9" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonata": { - "version": "2.0.5", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonschema": { - "version": "1.4.1", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "license": "MIT", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jsonwebtoken/node_modules/jwa": { - "version": "1.4.1", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jsonwebtoken/node_modules/jws": { - "version": "3.2.2", - "license": "MIT", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dev": true, - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/jstransformer": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-promise": "^2.0.0", - "promise": "^7.0.1" - } - }, - "node_modules/jstransformer/node_modules/is-promise": { - "version": "2.2.2", - "dev": true, - "license": "MIT" - }, - "node_modules/junk": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jwa": { - "version": "2.0.0", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jwks-rsa": { - "version": "3.1.0", - "license": "MIT", - "dependencies": { - "@types/express": "^4.17.17", - "@types/jsonwebtoken": "^9.0.2", - "debug": "^4.3.4", - "jose": "^4.14.6", - "limiter": "^1.1.5", - "lru-memoizer": "^2.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/jws": { - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/keygrip": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "tsscmp": "1.0.6" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/koa": { - "version": "2.15.2", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "^1.3.5", - "cache-content-type": "^1.0.0", - "content-disposition": "~0.5.2", - "content-type": "^1.0.4", - "cookies": "~0.9.0", - "debug": "^4.3.2", - "delegates": "^1.0.0", - "depd": "^2.0.0", - "destroy": "^1.0.4", - "encodeurl": "^1.0.2", - "escape-html": "^1.0.3", - "fresh": "~0.5.2", - "http-assert": "^1.3.0", - "http-errors": "^1.6.3", - "is-generator-function": "^1.0.7", - "koa-compose": "^4.1.0", - "koa-convert": "^2.0.0", - "on-finished": "^2.3.0", - "only": "~0.0.2", - "parseurl": "^1.3.2", - "statuses": "^1.5.0", - "type-is": "^1.6.16", - "vary": "^1.1.2" - }, - "engines": { - "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" - } - }, - "node_modules/koa-compose": { - "version": "4.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/koa-convert": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "co": "^4.6.0", - "koa-compose": "^4.1.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/koa-etag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "etag": "^1.8.1" - } - }, - "node_modules/koa-send": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "http-errors": "^1.7.3", - "resolve-path": "^1.4.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/koa-send/node_modules/depd": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/koa-send/node_modules/http-errors": { - "version": "1.8.1", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/koa-send/node_modules/statuses": { - "version": "1.5.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/koa-static": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.1.0", - "koa-send": "^5.0.0" - }, - "engines": { - "node": ">= 7.6.0" - } - }, - "node_modules/koa-static/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/koa/node_modules/http-errors": { - "version": "1.8.1", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/koa/node_modules/http-errors/node_modules/depd": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/koa/node_modules/statuses": { - "version": "1.5.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lighthouse-logger": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", - "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", - "dev": true, - "dependencies": { - "debug": "^2.6.9", - "marky": "^1.2.2" - } - }, - "node_modules/lighthouse-logger/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/lighthouse-logger/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/limiter": { - "version": "1.1.5" - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "dev": true, - "license": "MIT" - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "uc.micro": "^2.0.0" - } - }, - "node_modules/liquidjs": { - "version": "10.10.2", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^10.0.0" - }, - "bin": { - "liquid": "bin/liquid.js", - "liquidjs": "bin/liquid.js" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/liquidjs" - } - }, - "node_modules/liquidjs/node_modules/commander": { - "version": "10.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/list-to-array": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/lit": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lit/-/lit-3.2.0.tgz", - "integrity": "sha512-s6tI33Lf6VpDu7u4YqsSX78D28bYQulM+VAzsGch4fx2H0eLZnJsUBsPWmGYSGoKDNbjtRv02rio1o+UdPVwvw==", - "dependencies": { - "@lit/reactive-element": "^2.0.4", - "lit-element": "^4.1.0", - "lit-html": "^3.2.0" - } - }, - "node_modules/lit-element": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.1.0.tgz", - "integrity": "sha512-gSejRUQJuMQjV2Z59KAS/D4iElUhwKpIyJvZ9w+DIagIQjfJnhR20h2Q5ddpzXGS+fF0tMZ/xEYGMnKmaI/iww==", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.2.0", - "@lit/reactive-element": "^2.0.4", - "lit-html": "^3.2.0" - } - }, - "node_modules/lit-html": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.2.0.tgz", - "integrity": "sha512-pwT/HwoxqI9FggTrYVarkBKFN9MlTUpLrDHubTmW4SrkL3kkqW5gxwbxMMUnbbRHBC0WTZnYHcjDSCM559VyfA==", - "dependencies": { - "@types/trusted-types": "^2.0.2" - } - }, - "node_modules/lite-youtube-embed": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lite-youtube-embed/-/lite-youtube-embed-0.3.3.tgz", - "integrity": "sha512-gFfVVnj6NRjxVfJKo3qoLtpi0v5mn3AcR4eKD45wrxQuxzveFJUb+7Cr6uV6n+DjO8X3p0UzPPquhGt0H/y+NA==" - }, - "node_modules/litegraph.js": { - "version": "0.7.18", - "license": "MIT" - }, - "node_modules/load-json-file": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "license": "MIT" - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "license": "MIT" - }, - "node_modules/lodash.deburr": { - "version": "4.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "license": "MIT" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "license": "MIT" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "license": "MIT" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "license": "MIT" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "license": "MIT" - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "license": "MIT" - }, - "node_modules/lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "5.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/log-update/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/long": { - "version": "5.2.3", - "license": "Apache-2.0" - }, - "node_modules/loupe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", - "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "node_modules/lru-cache": { - "version": "10.2.0", - "dev": true, - "license": "ISC", - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/lru-memoizer": { - "version": "2.2.0", - "license": "MIT", - "dependencies": { - "lodash.clonedeep": "^4.5.0", - "lru-cache": "~4.0.0" - } - }, - "node_modules/lru-memoizer/node_modules/lru-cache": { - "version": "4.0.2", - "license": "ISC", - "dependencies": { - "pseudomap": "^1.0.1", - "yallist": "^2.0.0" - } - }, - "node_modules/lru-memoizer/node_modules/yallist": { - "version": "2.1.2", - "license": "ISC" - }, - "node_modules/luxon": { - "version": "3.4.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "license": "ISC" - }, - "node_modules/makeerror": { - "version": "1.0.12", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/map-age-cleaner": { - "version": "0.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "p-defer": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/markdown-it": { - "version": "14.1.0", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/markdown-it-github-alerts": { - "version": "0.3.0", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "markdown-it": "^14.0.0" - } - }, - "node_modules/markdown-it-github-headings": { - "version": "2.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "github-slugger": "^1.1.1", - "innertext": "^1.0.1" - } - }, - "node_modules/markdown-it/node_modules/argparse": { - "version": "2.0.1", - "license": "Python-2.0" - }, - "node_modules/marked": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/marked-terminal": { - "version": "6.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^6.2.0", - "cardinal": "^2.1.1", - "chalk": "^5.3.0", - "cli-table3": "^0.6.3", - "node-emoji": "^2.1.3", - "supports-hyperlinks": "^3.0.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "marked": ">=1 <12" - } - }, - "node_modules/marked-terminal/node_modules/ansi-escapes": { - "version": "6.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/marked-terminal/node_modules/chalk": { - "version": "5.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/marky": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", - "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", - "dev": true - }, - "node_modules/matcher": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/maximatch": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-differ": "^1.0.0", - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "minimatch": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/maximatch/node_modules/array-differ": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/maximatch/node_modules/array-union": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/maximatch/node_modules/arrify": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/maximatch/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/maximatch/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/md5-hex": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "blueimp-md5": "^2.10.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mdurl": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mem": { - "version": "9.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "map-age-cleaner": "^0.1.3", - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sindresorhus/mem?sponsor=1" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/mime": { - "version": "3.0.0", - "devOptional": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mitt": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "license": "MIT" - }, - "node_modules/moo": { - "version": "0.5.2", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/morphdom": { - "version": "2.7.2", - "dev": true, - "license": "MIT" - }, - "node_modules/mri": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "license": "MIT" - }, - "node_modules/multimatch": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimatch": "^3.0.3", - "array-differ": "^3.0.0", - "array-union": "^2.1.0", - "arrify": "^2.0.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/multimatch/node_modules/arrify": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/multimatch/node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/multimatch/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mustache": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/nanocolors": { - "version": "0.2.13", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.7", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "license": "MIT" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "dev": true, - "license": "MIT" - }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/node-abi": { - "version": "3.67.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.67.0.tgz", - "integrity": "sha512-bLn/fU/ALVBE9wj+p4Y21ZJWYFjUXLXPi/IewyLZkx3ApxKDNBWCKdReeKOtD8dWpOdDCeMyLh6ZewzcLsG2Nw==", - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-emoji": { - "version": "2.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^4.6.0", - "char-regex": "^1.0.2", - "emojilib": "^2.4.0", - "skin-tone": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "license": "MIT" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "license": "BSD-2-Clause" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/node-releases": { - "version": "2.0.14", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/nofilter": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.19" - } - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm": { - "version": "10.8.3", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.3.tgz", - "integrity": "sha512-0IQlyAYvVtQ7uOhDFYZCGK8kkut2nh8cpAdA9E6FvRSJaTgtZRZgNjlC5ZCct//L73ygrpY93CxXpRJDtNqPVg==", - "bundleDependencies": [ - "@isaacs/string-locale-compare", - "@npmcli/arborist", - "@npmcli/config", - "@npmcli/fs", - "@npmcli/map-workspaces", - "@npmcli/package-json", - "@npmcli/promise-spawn", - "@npmcli/redact", - "@npmcli/run-script", - "@sigstore/tuf", - "abbrev", - "archy", - "cacache", - "chalk", - "ci-info", - "cli-columns", - "fastest-levenshtein", - "fs-minipass", - "glob", - "graceful-fs", - "hosted-git-info", - "ini", - "init-package-json", - "is-cidr", - "json-parse-even-better-errors", - "libnpmaccess", - "libnpmdiff", - "libnpmexec", - "libnpmfund", - "libnpmhook", - "libnpmorg", - "libnpmpack", - "libnpmpublish", - "libnpmsearch", - "libnpmteam", - "libnpmversion", - "make-fetch-happen", - "minimatch", - "minipass", - "minipass-pipeline", - "ms", - "node-gyp", - "nopt", - "normalize-package-data", - "npm-audit-report", - "npm-install-checks", - "npm-package-arg", - "npm-pick-manifest", - "npm-profile", - "npm-registry-fetch", - "npm-user-validate", - "p-map", - "pacote", - "parse-conflict-json", - "proc-log", - "qrcode-terminal", - "read", - "semver", - "spdx-expression-parse", - "ssri", - "supports-color", - "tar", - "text-table", - "tiny-relative-date", - "treeverse", - "validate-npm-package-name", - "which", - "write-file-atomic" - ], - "dev": true, - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^7.5.4", - "@npmcli/config": "^8.3.4", - "@npmcli/fs": "^3.1.1", - "@npmcli/map-workspaces": "^3.0.6", - "@npmcli/package-json": "^5.2.0", - "@npmcli/promise-spawn": "^7.0.2", - "@npmcli/redact": "^2.0.1", - "@npmcli/run-script": "^8.1.0", - "@sigstore/tuf": "^2.3.4", - "abbrev": "^2.0.0", - "archy": "~1.0.0", - "cacache": "^18.0.4", - "chalk": "^5.3.0", - "ci-info": "^4.0.0", - "cli-columns": "^4.0.0", - "fastest-levenshtein": "^1.0.16", - "fs-minipass": "^3.0.3", - "glob": "^10.4.5", - "graceful-fs": "^4.2.11", - "hosted-git-info": "^7.0.2", - "ini": "^4.1.3", - "init-package-json": "^6.0.3", - "is-cidr": "^5.1.0", - "json-parse-even-better-errors": "^3.0.2", - "libnpmaccess": "^8.0.6", - "libnpmdiff": "^6.1.4", - "libnpmexec": "^8.1.4", - "libnpmfund": "^5.0.12", - "libnpmhook": "^10.0.5", - "libnpmorg": "^6.0.6", - "libnpmpack": "^7.0.4", - "libnpmpublish": "^9.0.9", - "libnpmsearch": "^7.0.6", - "libnpmteam": "^6.0.5", - "libnpmversion": "^6.0.3", - "make-fetch-happen": "^13.0.1", - "minimatch": "^9.0.5", - "minipass": "^7.1.1", - "minipass-pipeline": "^1.2.4", - "ms": "^2.1.2", - "node-gyp": "^10.2.0", - "nopt": "^7.2.1", - "normalize-package-data": "^6.0.2", - "npm-audit-report": "^5.0.0", - "npm-install-checks": "^6.3.0", - "npm-package-arg": "^11.0.3", - "npm-pick-manifest": "^9.1.0", - "npm-profile": "^10.0.0", - "npm-registry-fetch": "^17.1.0", - "npm-user-validate": "^2.0.1", - "p-map": "^4.0.0", - "pacote": "^18.0.6", - "parse-conflict-json": "^3.0.1", - "proc-log": "^4.2.0", - "qrcode-terminal": "^0.12.0", - "read": "^3.0.1", - "semver": "^7.6.3", - "spdx-expression-parse": "^4.0.0", - "ssri": "^10.0.6", - "supports-color": "^9.4.0", - "tar": "^6.2.1", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "treeverse": "^3.0.0", - "validate-npm-package-name": "^5.0.1", - "which": "^4.0.0", - "write-file-atomic": "^5.0.1" - }, - "bin": { - "npm": "bin/npm-cli.js", - "npx": "bin/npx-cli.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm-ci": { - "version": "0.0.2", - "dev": true, - "license": "ISC" - }, - "node_modules/npm-package-arg": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz", - "integrity": "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==", - "dev": true, - "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^4.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm-package-arg/node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", - "dev": true, - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui": { - "version": "8.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/@isaacs/string-locale-compare": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/@npmcli/agent": { - "version": "2.2.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "7.5.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/fs": "^3.1.1", - "@npmcli/installed-package-contents": "^2.1.0", - "@npmcli/map-workspaces": "^3.0.2", - "@npmcli/metavuln-calculator": "^7.1.1", - "@npmcli/name-from-folder": "^2.0.0", - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^5.1.0", - "@npmcli/query": "^3.1.0", - "@npmcli/redact": "^2.0.0", - "@npmcli/run-script": "^8.1.0", - "bin-links": "^4.0.4", - "cacache": "^18.0.3", - "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^7.0.2", - "json-parse-even-better-errors": "^3.0.2", - "json-stringify-nice": "^1.1.4", - "lru-cache": "^10.2.2", - "minimatch": "^9.0.4", - "nopt": "^7.2.1", - "npm-install-checks": "^6.2.0", - "npm-package-arg": "^11.0.2", - "npm-pick-manifest": "^9.0.1", - "npm-registry-fetch": "^17.0.1", - "pacote": "^18.0.6", - "parse-conflict-json": "^3.0.0", - "proc-log": "^4.2.0", - "proggy": "^2.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^3.0.1", - "read-package-json-fast": "^3.0.2", - "semver": "^7.3.7", - "ssri": "^10.0.6", - "treeverse": "^3.0.0", - "walk-up-path": "^3.0.1" - }, - "bin": { - "arborist": "bin/index.js" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/config": { - "version": "8.3.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/map-workspaces": "^3.0.2", - "@npmcli/package-json": "^5.1.1", - "ci-info": "^4.0.0", - "ini": "^4.1.2", - "nopt": "^7.2.1", - "proc-log": "^4.2.0", - "semver": "^7.3.5", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/fs": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/git": { - "version": "5.0.8", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/promise-spawn": "^7.0.0", - "ini": "^4.1.3", - "lru-cache": "^10.0.1", - "npm-pick-manifest": "^9.0.0", - "proc-log": "^4.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^4.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/installed-package-contents": { - "version": "2.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "bin": { - "installed-package-contents": "bin/index.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "3.0.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/name-from-folder": "^2.0.0", - "glob": "^10.2.2", - "minimatch": "^9.0.0", - "read-package-json-fast": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "7.1.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cacache": "^18.0.0", - "json-parse-even-better-errors": "^3.0.0", - "pacote": "^18.0.0", - "proc-log": "^4.1.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/name-from-folder": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/node-gyp": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "5.2.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^5.0.0", - "glob": "^10.2.2", - "hosted-git-info": "^7.0.0", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "proc-log": "^4.0.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "7.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "which": "^4.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/query": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/redact": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "8.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^5.0.0", - "@npmcli/promise-spawn": "^7.0.0", - "node-gyp": "^10.0.0", - "proc-log": "^4.0.0", - "which": "^4.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/@sigstore/bundle": { - "version": "2.3.2", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/core": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/protobuf-specs": { - "version": "0.3.2", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/sign": { - "version": "2.3.2", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "make-fetch-happen": "^13.0.1", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "2.3.4", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2", - "tuf-js": "^2.2.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/verify": { - "version": "1.2.1", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.1.0", - "@sigstore/protobuf-specs": "^0.3.2" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@tufjs/canonical-json": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@tufjs/models": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/abbrev": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/agent-base": { - "version": "7.1.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/aggregate-error": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-styles": { - "version": "6.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/aproba": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/archy": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/bin-links": { - "version": "4.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cmd-shim": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "read-cmd-shim": "^4.0.0", - "write-file-atomic": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/binary-extensions": { - "version": "2.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/npm/node_modules/cacache": { - "version": "18.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/chalk": { - "version": "5.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/npm/node_modules/chownr": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ci-info": { - "version": "4.0.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/cidr-regex": { - "version": "4.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "ip-regex": "^5.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/clean-stack": { - "version": "2.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/cli-columns": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/cmd-shim": { - "version": "6.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/npm/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/common-ancestor-path": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/cross-spawn": { - "version": "7.0.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cssesc": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/debug": { - "version": "4.3.6", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/npm/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/diff": { - "version": "5.2.0", - "dev": true, - "inBundle": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/npm/node_modules/eastasianwidth": { - "version": "0.2.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/encoding": { - "version": "0.1.13", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/npm/node_modules/env-paths": { - "version": "2.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/err-code": { - "version": "2.0.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/exponential-backoff": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "Apache-2.0" - }, - "node_modules/npm/node_modules/fastest-levenshtein": { - "version": "1.0.16", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/npm/node_modules/foreground-child": { - "version": "3.3.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/fs-minipass": { - "version": "3.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/glob": { - "version": "10.4.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/graceful-fs": { - "version": "4.2.11", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/hosted-git-info": { - "version": "7.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/http-cache-semantics": { - "version": "4.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause" - }, - "node_modules/npm/node_modules/http-proxy-agent": { - "version": "7.0.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/https-proxy-agent": { - "version": "7.0.5", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/iconv-lite": { - "version": "0.6.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/ignore-walk": { - "version": "6.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/npm/node_modules/indent-string": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ini": { - "version": "4.1.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/init-package-json": { - "version": "6.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/package-json": "^5.0.0", - "npm-package-arg": "^11.0.0", - "promzard": "^1.0.0", - "read": "^3.0.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/ip-address": { - "version": "9.0.5", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/npm/node_modules/ip-regex": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/is-cidr": { - "version": "5.1.0", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "cidr-regex": "^4.1.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/is-lambda": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/jackspeak": { - "version": "3.4.3", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/npm/node_modules/jsbn": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/json-parse-even-better-errors": { - "version": "3.0.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/json-stringify-nice": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/jsonparse": { - "version": "1.3.1", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff-apply": { - "version": "5.5.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/libnpmaccess": { - "version": "8.0.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-package-arg": "^11.0.2", - "npm-registry-fetch": "^17.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmdiff": { - "version": "6.1.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^7.5.4", - "@npmcli/installed-package-contents": "^2.1.0", - "binary-extensions": "^2.3.0", - "diff": "^5.1.0", - "minimatch": "^9.0.4", - "npm-package-arg": "^11.0.2", - "pacote": "^18.0.6", - "tar": "^6.2.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmexec": { - "version": "8.1.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^7.5.4", - "@npmcli/run-script": "^8.1.0", - "ci-info": "^4.0.0", - "npm-package-arg": "^11.0.2", - "pacote": "^18.0.6", - "proc-log": "^4.2.0", - "read": "^3.0.1", - "read-package-json-fast": "^3.0.2", - "semver": "^7.3.7", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmfund": { - "version": "5.0.12", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^7.5.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmhook": { - "version": "10.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^17.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmorg": { - "version": "6.0.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^17.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmpack": { - "version": "7.0.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^7.5.4", - "@npmcli/run-script": "^8.1.0", - "npm-package-arg": "^11.0.2", - "pacote": "^18.0.6" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmpublish": { - "version": "9.0.9", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "ci-info": "^4.0.0", - "normalize-package-data": "^6.0.1", - "npm-package-arg": "^11.0.2", - "npm-registry-fetch": "^17.0.1", - "proc-log": "^4.2.0", - "semver": "^7.3.7", - "sigstore": "^2.2.0", - "ssri": "^10.0.6" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmsearch": { - "version": "7.0.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^17.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmteam": { - "version": "6.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^17.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/libnpmversion": { - "version": "6.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^5.0.7", - "@npmcli/run-script": "^8.1.0", - "json-parse-even-better-errors": "^3.0.2", - "proc-log": "^4.2.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/lru-cache": { - "version": "10.4.3", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/make-fetch-happen": { - "version": "13.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", - "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/minimatch": { - "version": "9.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/minipass": { - "version": "7.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npm/node_modules/minipass-collect": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npm/node_modules/minipass-fetch": { - "version": "3.0.5", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/minipass-flush": { - "version": "1.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline": { - "version": "1.2.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minizlib": { - "version": "2.1.2", - "dev": true, - "inBundle": true, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.2.tgz", + "integrity": "sha512-3HRQLUQbpBDMmzoxPJYd3W6vrVHOo2cVW8RUo87Xz0JPJcBLBr5kZ1pGcQAhdZgX9VV7NbGNipah1omKKe23/g==", + "cpu": [ + "ppc64" + ], "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/npm/node_modules/mkdirp": { - "version": "1.0.4", - "dev": true, - "inBundle": true, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.2.tgz", + "integrity": "sha512-fMjKi+ojnmIvhk34gZP94vjogXNNUKMEYs+EDaB/5TG/wUkoeua7p7VCHnE6T2Tx+iaghAqQX8teQzcvrYpaQA==", + "cpu": [ + "riscv64" + ], "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/mute-stream": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/npm/node_modules/negotiator": { - "version": "0.6.3", - "dev": true, - "inBundle": true, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.2.tgz", + "integrity": "sha512-XuGFGU+VwUUV5kLvoAdi0Wz5Xbh2SrjIxCtZj6Wq8MDp4bflb/+ThZsVxokM7n0pcbkEr2h5/pzqzDYI7cCgLQ==", + "cpu": [ + "riscv64" + ], "license": "MIT", - "engines": { - "node": ">= 0.6" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/npm/node_modules/node-gyp": { - "version": "10.2.0", - "dev": true, - "inBundle": true, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.2.tgz", + "integrity": "sha512-w6yjZF0P+NGzWR3AXWX9zc0DNEGdtvykB03uhonSHMRa+oWA6novflo2WaJr6JZakG2ucsyb+rvhrKac6NIy+w==", + "cpu": [ + "s390x" + ], "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^4.1.0", - "semver": "^7.3.5", - "tar": "^6.2.1", - "which": "^4.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/npm/node_modules/nopt": { - "version": "7.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.2.tgz", + "integrity": "sha512-yo8d6tdfdeBArzC7T/PnHd7OypfI9cbuZzPnzLJIyKYFhAQ8SvlkKtKBMbXDxe1h03Rcr7u++nFS7tqXz87Gtw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/npm/node_modules/normalize-package-data": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^7.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.2.tgz", + "integrity": "sha512-ah59c1YkCxKExPP8O9PwOvs+XRLKwh/mV+3YdKqQ5AMQ0r4M4ZDuOrpWkUaqO7fzAHdINzV9tEVu8vNw48z0lA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/npm/node_modules/npm-audit-report": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.2.tgz", + "integrity": "sha512-4VEd19Wmhr+Zy7hbUsFZ6YXEiP48hE//KPLCSVNY5RMGX2/7HZ+QkN55a3atM1C/BZCGIgqN+xrVgtdak2S9+A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] }, - "node_modules/npm/node_modules/npm-bundled": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.2.tgz", + "integrity": "sha512-IlbHFYc/pQCgew/d5fslcy1KEaYVCJ44G8pajugd8VoOEI8ODhtb/j8XMhLpwHCMB3yk2J07ctup10gpw2nyMA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/npm/node_modules/npm-install-checks": { - "version": "6.3.0", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.2.tgz", + "integrity": "sha512-lNlPEGgdUfSzdCWU176ku/dQRnA7W+Gp8d+cWv73jYrb8uT7HTVVxq62DUYxjbaByuf1Yk0RIIAbDzp+CnOTFg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/npm/node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.2.tgz", + "integrity": "sha512-S6YojNVrHybQis2lYov1sd+uj7K0Q05NxHcGktuMMdIQ2VixGwAfbJ23NnlvvVV1bdpR2m5MsNBViHJKcA4ADw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/npm/node_modules/npm-package-arg": { - "version": "11.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^4.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.2.tgz", + "integrity": "sha512-k+/Rkcyx//P6fetPoLMb8pBeqJBNGx81uuf7iljX9++yNBVRDQgD04L+SVXmXmh5ZP4/WOp4mWF0kmi06PW2tA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/npm/node_modules/npm-packlist": { - "version": "8.0.2", + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^6.0.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "license": "MIT", + "optional": true, + "peer": true }, - "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "9.1.0", + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^11.0.0", - "semver": "^7.3.5" - }, + "license": "MIT", "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/npm-profile": { - "version": "10.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^17.0.1", - "proc-log": "^4.0.0" + "node": ">=18" }, - "engines": { - "node": ">=18.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "17.1.0", + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/redact": "^2.0.0", - "jsonparse": "^1.3.1", - "make-fetch-happen": "^13.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minizlib": "^2.1.2", - "npm-package-arg": "^11.0.0", - "proc-log": "^4.0.0" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } + "license": "MIT" }, - "node_modules/npm/node_modules/npm-user-validate": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "license": "MIT", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 10" } }, - "node_modules/npm/node_modules/p-map": { - "version": "4.0.0", + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", "dev": true, - "inBundle": true, "license": "MIT", "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@types/connect": "*", + "@types/node": "*" } }, - "node_modules/npm/node_modules/package-json-from-dist": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0" + "node_modules/@types/caseless": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", + "license": "MIT" }, - "node_modules/npm/node_modules/pacote": { - "version": "18.0.6", + "node_modules/@types/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-kCFuWS0ebDbmxs0AXYn6e2r2nrGAb5KwQhknjSPSPgJcGd8+HVSILlUyFhGqML2gk39HcG7D1ydW9/qpYkN00Q==", "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^5.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/package-json": "^5.1.0", - "@npmcli/promise-spawn": "^7.0.0", - "@npmcli/run-script": "^8.0.0", - "cacache": "^18.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^11.0.0", - "npm-packlist": "^8.0.0", - "npm-pick-manifest": "^9.0.0", - "npm-registry-fetch": "^17.0.0", - "proc-log": "^4.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^2.2.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "bin/index.js" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/node": "*" } }, - "node_modules/npm/node_modules/parse-conflict-json": { - "version": "3.0.1", + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, - "inBundle": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "just-diff": "^6.0.0", - "just-diff-apply": "^5.2.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "@types/node": "*" } }, - "node_modules/npm/node_modules/path-key": { - "version": "3.1.1", + "node_modules/@types/cookie-parser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.10.tgz", + "integrity": "sha512-B4xqkqfZ8Wek+rCOeRxsjMS9OgvzebEzzLYw7NHYuvzb7IdxOkI0ZHGgeEBX4PUM7QGVvNSK60T3OvWj3YfBRg==", "dev": true, - "inBundle": true, "license": "MIT", - "engines": { - "node": ">=8" + "peerDependencies": { + "@types/express": "*" } }, - "node_modules/npm/node_modules/path-scurry": { - "version": "1.11.1", + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@types/node": "*" } }, - "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.1.2", + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.5.tgz", + "integrity": "sha512-LuIQOcb6UmnF7C1PCFmEU1u2hmiHL43fgFQX67sN3H4Z+0Yk0Neo++mFsBjhOAuLzvlQeqAAkeDOZrJs9rzumQ==", "dev": true, - "inBundle": true, "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "^1" } }, - "node_modules/npm/node_modules/proc-log": { - "version": "4.2.0", + "node_modules/@types/express-serve-static-core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.0.tgz", + "integrity": "sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==", "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" } }, - "node_modules/npm/node_modules/proggy": { - "version": "2.0.0", + "node_modules/@types/flubber": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@types/flubber/-/flubber-0.4.0.tgz", + "integrity": "sha512-q9u6zseKgOBc0sAn/aPyi0vMNtXiLrNHSvj/tMXg+X2vk0jwX7obXgLISBmryGFvfszbId1JGT/8CcwB3vC6yg==", "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "license": "MIT" }, - "node_modules/npm/node_modules/promise-all-reject-late": { - "version": "1.0.1", + "node_modules/@types/gapi": { + "version": "0.0.47", + "resolved": "https://registry.npmjs.org/@types/gapi/-/gapi-0.0.47.tgz", + "integrity": "sha512-/ZsLuq6BffMgbKMtZyDZ8vwQvTyKhKQ1G2K6VyWCgtHHhfSSXbk4+4JwImZiTjWNXfI2q1ZStAwFFHSkNoTkHA==", "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "MIT" }, - "node_modules/npm/node_modules/promise-call-limit": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node_modules/@types/gapi.client": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/gapi.client/-/gapi.client-1.0.8.tgz", + "integrity": "sha512-qJQUmmumbYym3Amax0S8CVzuSngcXsC1fJdwRS2zeW5lM63zXkw4wJFP+bG0jzgi0R6EsJKoHnGNVTDbOyG1ng==", + "license": "MIT" + }, + "node_modules/@types/gapi.client.calendar-v3": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/gapi.client.calendar-v3/-/gapi.client.calendar-v3-0.0.4.tgz", + "integrity": "sha512-EwXzPhk98ef+esL1R951e3HFeMQSP6hSBv+YBbaAJoOLLRANV2JY5KHOImBSkk7HKt1PiarQGx5BD8+4eHeeIQ==", + "license": "MIT", + "dependencies": { + "@maxim_mazurok/gapi.client.calendar-v3": "latest" } }, - "node_modules/npm/node_modules/promise-inflight": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" + "node_modules/@types/gapi.client.discovery-v1": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/gapi.client.discovery-v1/-/gapi.client.discovery-v1-0.0.4.tgz", + "integrity": "sha512-uevhRumNE65F5mf2gABLaReOmbFSXONuzFZjNR3dYv6BmkHg+wciubHrfBAsp3554zNo3Dcg6dUAlwMqQfpwjQ==", + "license": "MIT", + "dependencies": { + "@maxim_mazurok/gapi.client.discovery-v1": "latest" + } }, - "node_modules/npm/node_modules/promise-retry": { - "version": "2.0.1", - "dev": true, - "inBundle": true, + "node_modules/@types/gapi.client.drive-v3": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@types/gapi.client.drive-v3/-/gapi.client.drive-v3-0.0.5.tgz", + "integrity": "sha512-yYBxiqMqJVBg4bns4Q28+f2XdJnd3tVA9dxQX1lXMVmzT2B+pZdyCi1u9HLwGveVlookSsAXuqfLfS9KO6MF6w==", "license": "MIT", "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" + "@maxim_mazurok/gapi.client.drive-v3": "latest" } }, - "node_modules/npm/node_modules/promzard": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", + "node_modules/@types/gapi.client.gmail-v1": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/gapi.client.gmail-v1/-/gapi.client.gmail-v1-0.0.4.tgz", + "integrity": "sha512-eky4t4mb6emgvyJh+qhDJPX3/nhXg/QroOVLAjM13Facyz3zfC7PHuRTCDARR7PFUh3V4nqLhhysq/vv0mLe4g==", + "license": "MIT", "dependencies": { - "read": "^3.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "@maxim_mazurok/gapi.client.gmail-v1": "latest" } }, - "node_modules/npm/node_modules/qrcode-terminal": { - "version": "0.12.0", + "node_modules/@types/google.picker": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/google.picker/-/google.picker-0.0.51.tgz", + "integrity": "sha512-z6o2J4PQTcXvlW1rtgQx65d5uEF+rMI1hzrnazKQxBONdEuYAr4AeOSH2KZy12WHPmqMX+aWYyfcZ0uktBBhhA==", "dev": true, - "inBundle": true, - "bin": { - "qrcode-terminal": "bin/qrcode-terminal.js" - } + "license": "MIT" }, - "node_modules/npm/node_modules/read": { - "version": "3.0.1", + "node_modules/@types/gtag.js": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.20.tgz", + "integrity": "sha512-wwAbk3SA2QeU67unN7zPxjEHmPmlXwZXZvQEpbEUQuMCRGgKyE1m6XDuTUA9b6pCGb/GqJmdfMOY5LuDjJSbbg==", "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "mute-stream": "^1.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "license": "MIT" }, - "node_modules/npm/node_modules/read-cmd-shim": { - "version": "4.0.0", + "node_modules/@types/har-format": { + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.16.tgz", + "integrity": "sha512-fluxdy7ryD3MV6h8pTfTYpy/xQzCFC7m89nOH9y94cNqJ1mDIDPut7MnRHI3F6qRmh/cT2fUjG1MLdCNb4hE9A==", "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "license": "MIT" }, - "node_modules/npm/node_modules/read-package-json-fast": { - "version": "3.0.2", + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } + "license": "MIT" }, - "node_modules/npm/node_modules/retry": { - "version": "0.12.0", + "node_modules/@types/jsdom": { + "version": "27.0.0", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-27.0.0.tgz", + "integrity": "sha512-NZyFl/PViwKzdEkQg96gtnB8wm+1ljhdDay9ahn4hgb+SfVtPCbm3TlmDUFXTA+MGN3CijicnMhG18SI5H3rFw==", "dev": true, - "inBundle": true, "license": "MIT", - "engines": { - "node": ">= 4" + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" } }, - "node_modules/npm/node_modules/safer-buffer": { - "version": "2.1.2", + "node_modules/@types/jwt-decode": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/jwt-decode/-/jwt-decode-2.2.1.tgz", + "integrity": "sha512-aWw2YTtAdT7CskFyxEX2K21/zSDStuf/ikI3yBqmwpwJF0pS+/IX5DWv+1UFffZIbruP6cnT9/LAJV1gFwAT1A==", "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true + "license": "MIT" }, - "node_modules/npm/node_modules/semver": { - "version": "7.6.3", + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", "dev": true, - "inBundle": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } + "license": "MIT" }, - "node_modules/npm/node_modules/shebang-command": { - "version": "2.0.0", + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "dev": true, - "inBundle": true, "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" + "@types/linkify-it": "^5", + "@types/mdurl": "^2" } }, - "node_modules/npm/node_modules/shebang-regex": { - "version": "3.0.0", + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/npm/node_modules/signal-exit": { - "version": "4.1.0", + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "MIT" }, - "node_modules/npm/node_modules/sigstore": { - "version": "2.3.1", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", + "node_modules/@types/node": { + "version": "22.19.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz", + "integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==", + "license": "MIT", "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "@sigstore/sign": "^2.3.2", - "@sigstore/tuf": "^2.3.4", - "@sigstore/verify": "^1.2.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" + "undici-types": "~6.21.0" } }, - "node_modules/npm/node_modules/smart-buffer": { - "version": "4.2.0", + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } + "license": "MIT" }, - "node_modules/npm/node_modules/socks": { - "version": "2.8.3", + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true, - "inBundle": true, + "license": "MIT" + }, + "node_modules/@types/request": { + "version": "2.48.13", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz", + "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.5" } }, - "node_modules/npm/node_modules/socks-proxy-agent": { - "version": "8.0.4", + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", "dev": true, - "inBundle": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" + "@types/node": "*" } }, - "node_modules/npm/node_modules/spdx-correct": { - "version": "3.2.0", + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", "dev": true, - "inBundle": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" } }, - "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { - "version": "3.0.1", + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", "dev": true, - "inBundle": true, "license": "MIT", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "@types/mime": "^1", + "@types/node": "*" } }, - "node_modules/npm/node_modules/spdx-exceptions": { - "version": "2.5.0", - "dev": true, - "inBundle": true, - "license": "CC-BY-3.0" + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "license": "MIT" }, - "node_modules/npm/node_modules/spdx-expression-parse": { - "version": "4.0.0", + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.47.0.tgz", + "integrity": "sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==", "dev": true, - "inBundle": true, "license": "MIT", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/type-utils": "8.47.0", + "@typescript-eslint/utils": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.47.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.18", - "dev": true, - "inBundle": true, - "license": "CC0-1.0" - }, - "node_modules/npm/node_modules/sprintf-js": { - "version": "1.1.3", - "dev": true, - "inBundle": true, - "license": "BSD-3-Clause" - }, - "node_modules/npm/node_modules/ssri": { - "version": "10.0.6", + "node_modules/@typescript-eslint/parser": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.47.0.tgz", + "integrity": "sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==", "dev": true, - "inBundle": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^7.0.3" + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", + "debug": "^4.3.4" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/npm/node_modules/string-width": { - "version": "4.2.3", + "node_modules/@typescript-eslint/project-service": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz", + "integrity": "sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==", "dev": true, - "inBundle": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@typescript-eslint/tsconfig-utils": "^8.47.0", + "@typescript-eslint/types": "^8.47.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/npm/node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.47.0.tgz", + "integrity": "sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==", "dev": true, - "inBundle": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/npm/node_modules/strip-ansi": { - "version": "6.0.1", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.47.0.tgz", + "integrity": "sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==", "dev": true, - "inBundle": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/npm/node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.47.0.tgz", + "integrity": "sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A==", "dev": true, - "inBundle": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0", + "@typescript-eslint/utils": "8.47.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/npm/node_modules/supports-color": { - "version": "9.4.0", + "node_modules/@typescript-eslint/types": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.47.0.tgz", + "integrity": "sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==", "dev": true, - "inBundle": true, "license": "MIT", "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/npm/node_modules/tar": { - "version": "6.2.1", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.47.0.tgz", + "integrity": "sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==", "dev": true, - "inBundle": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "@typescript-eslint/project-service": "8.47.0", + "@typescript-eslint/tsconfig-utils": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", + "node_modules/@typescript-eslint/utils": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.47.0.tgz", + "integrity": "sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==", "dev": true, - "inBundle": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^3.0.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0" }, "engines": { - "node": ">= 8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.47.0.tgz", + "integrity": "sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==", "dev": true, - "inBundle": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "@typescript-eslint/types": "8.47.0", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/npm/node_modules/tar/node_modules/minipass": { - "version": "5.0.0", + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "inBundle": true, - "license": "ISC", + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/npm/node_modules/text-table": { - "version": "0.2.0", + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "dev": true, - "inBundle": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/npm/node_modules/tiny-relative-date": { - "version": "1.3.0", + "node_modules/@vercel/nft": { + "version": "0.29.4", + "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.29.4.tgz", + "integrity": "sha512-6lLqMNX3TuycBPABycx7A9F1bHQR7kiQln6abjFbPrf5C/05qHM9M5E4PeTE59c7z8g6vHnx1Ioihb2AQl7BTA==", "dev": true, - "inBundle": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@mapbox/node-pre-gyp": "^2.0.0", + "@rollup/pluginutils": "^5.1.3", + "acorn": "^8.6.0", + "acorn-import-attributes": "^1.9.5", + "async-sema": "^3.1.1", + "bindings": "^1.4.0", + "estree-walker": "2.0.2", + "glob": "^10.4.5", + "graceful-fs": "^4.2.9", + "node-gyp-build": "^4.2.2", + "picomatch": "^4.0.2", + "resolve-from": "^5.0.0" + }, + "bin": { + "nft": "out/cli.js" + }, + "engines": { + "node": ">=18" + } }, - "node_modules/npm/node_modules/treeverse": { - "version": "3.0.0", + "node_modules/abbrev": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", "dev": true, - "inBundle": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/npm/node_modules/tuf-js": { - "version": "2.2.1", - "dev": true, - "inBundle": true, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "license": "MIT", "dependencies": { - "@tufjs/models": "2.0.1", - "debug": "^4.3.4", - "make-fetch-happen": "^13.0.1" + "event-target-shim": "^5.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=6.5" } }, - "node_modules/npm/node_modules/unique-filename": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { - "unique-slug": "^4.0.0" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 0.6" } }, - "node_modules/npm/node_modules/unique-slug": { - "version": "4.0.0", + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" + "license": "MIT", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=0.4.0" } }, - "node_modules/npm/node_modules/util-deprecate": { - "version": "1.0.2", + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "dev": true, - "inBundle": true, - "license": "MIT" + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } }, - "node_modules/npm/node_modules/validate-npm-package-license": { - "version": "3.0.4", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { - "version": "3.0.1", + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, - "inBundle": true, "license": "MIT", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 14" } }, - "node_modules/npm/node_modules/walk-up-path": { - "version": "3.0.1", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "inBundle": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } }, - "node_modules/npm/node_modules/which": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", "dependencies": { - "isexe": "^3.1.1" + "ajv": "^8.0.0" }, - "bin": { - "node-which": "bin/which.js" + "peerDependencies": { + "ajv": "^8.0.0" }, - "engines": { - "node": "^16.13.0 || >=18.0.0" + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/npm/node_modules/which/node_modules/isexe": { - "version": "3.1.1", + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, - "inBundle": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=6" } }, - "node_modules/npm/node_modules/wrap-ansi": { - "version": "8.1.0", - "dev": true, - "inBundle": true, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/npm/node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, - "inBundle": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">= 8" } }, - "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "inBundle": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", "dev": true, - "inBundle": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "dev": true, - "inBundle": true, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", + "node_modules/arrgv": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz", + "integrity": "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==", "dev": true, - "inBundle": true, "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8.0.0" } }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", + "node_modules/arrify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", + "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", "dev": true, - "inBundle": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm/node_modules/write-file-atomic": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "license": "MIT", "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "retry": "0.13.1" } }, - "node_modules/npm/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "optional": true, - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "node_modules/async-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" } }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "node_modules/async-sema": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz", + "integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==", "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/nunjucks": { - "version": "3.2.4", + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/ava": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/ava/-/ava-6.4.1.tgz", + "integrity": "sha512-vxmPbi1gZx9zhAjHBgw81w/iEDKcrokeRk/fqDTyA2DQygZ0o+dUGRHFOtX8RA5N0heGJTTsIk7+xYxitDb61Q==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "a-sync-waterfall": "^1.0.0", - "asap": "^2.0.3", - "commander": "^5.1.0" + "@vercel/nft": "^0.29.4", + "acorn": "^8.15.0", + "acorn-walk": "^8.3.4", + "ansi-styles": "^6.2.1", + "arrgv": "^1.0.2", + "arrify": "^3.0.0", + "callsites": "^4.2.0", + "cbor": "^10.0.9", + "chalk": "^5.4.1", + "chunkd": "^2.0.1", + "ci-info": "^4.3.0", + "ci-parallel-vars": "^1.0.1", + "cli-truncate": "^4.0.0", + "code-excerpt": "^4.0.0", + "common-path-prefix": "^3.0.0", + "concordance": "^5.0.4", + "currently-unhandled": "^0.4.1", + "debug": "^4.4.1", + "emittery": "^1.2.0", + "figures": "^6.1.0", + "globby": "^14.1.0", + "ignore-by-default": "^2.1.0", + "indent-string": "^5.0.0", + "is-plain-object": "^5.0.0", + "is-promise": "^4.0.0", + "matcher": "^5.0.0", + "memoize": "^10.1.0", + "ms": "^2.1.3", + "p-map": "^7.0.3", + "package-config": "^5.0.0", + "picomatch": "^4.0.2", + "plur": "^5.1.0", + "pretty-ms": "^9.2.0", + "resolve-cwd": "^3.0.0", + "stack-utils": "^2.0.6", + "strip-ansi": "^7.1.0", + "supertap": "^3.0.1", + "temp-dir": "^3.0.0", + "write-file-atomic": "^6.0.0", + "yargs": "^17.7.2" }, "bin": { - "nunjucks-precompile": "bin/precompile" + "ava": "entrypoints/cli.mjs" }, "engines": { - "node": ">= 6.9.0" + "node": "^18.18 || ^20.8 || ^22 || ^23 || >=24" }, "peerDependencies": { - "chokidar": "^3.3.0" + "@ava/typescript": "*" }, "peerDependenciesMeta": { - "chokidar": { + "@ava/typescript": { "optional": true } } }, - "node_modules/nunjucks/node_modules/commander": { - "version": "5.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" }, - "node_modules/nwsapi": { - "version": "2.2.12", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", - "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", - "dev": true + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "require-from-string": "^2.0.2" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "dev": true, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", "license": "MIT", "engines": { - "node": ">= 0.4" + "node": "*" } }, - "node_modules/object.assign": { - "version": "4.1.5", + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object.fromentries": { - "version": "2.0.8", + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "file-uri-to-path": "1.0.0" } }, - "node_modules/object.groupby": { - "version": "1.0.3", + "node_modules/blueimp-md5": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", "dev": true, + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/object.values": { - "version": "1.2.0", - "dev": true, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "ms": "2.0.0" } }, - "node_modules/on-finished": { - "version": "2.4.1", + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "license": "MIT", "dependencies": { - "ee-first": "1.1.1" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "license": "MIT", - "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/once": { - "version": "1.4.0", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, - "node_modules/onetime": { - "version": "6.0.0", - "dev": true, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "license": "MIT", "dependencies": { - "mimic-fn": "^4.0.0" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/only": { - "version": "0.0.2", - "dev": true + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } }, - "node_modules/open": { - "version": "8.4.2", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" + "fill-range": "^7.1.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/openapi-types": { - "version": "12.1.3", - "license": "MIT" + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" }, - "node_modules/optionator": { - "version": "0.9.3", - "dev": true, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "license": "MIT", - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.8" } }, - "node_modules/ora": { - "version": "8.0.1", - "dev": true, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^4.0.0", - "cli-spinners": "^2.9.2", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.0.0", - "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.4" } }, - "node_modules/ora/node_modules/chalk": { - "version": "5.3.0", - "dev": true, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ora/node_modules/emoji-regex": { - "version": "10.3.0", - "dev": true, - "license": "MIT" - }, - "node_modules/ora/node_modules/is-unicode-supported": { - "version": "2.0.0", + "node_modules/callsites": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.2.0.tgz", + "integrity": "sha512-kfzR4zzQtAE9PC7CzZsjl3aBNbXWuXiSeOCdLcPpBfGW8YuCqQHcRPFDbr/BPVmd3EEPVpuFzLyuT/cUhPr4OQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/string-width": { - "version": "7.1.0", + "node_modules/cbor": { + "version": "10.0.11", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-10.0.11.tgz", + "integrity": "sha512-vIwORDd/WyB8Nc23o2zNN5RrtFGlR6Fca61TtjkUXueI3Jf2DOZDl1zsshvBntZ3wZHBM9ztjnkXSmzQDaq3WA==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" + "nofilter": "^3.0.2" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=20" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/outdent": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz", - "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==", - "dev": true - }, - "node_modules/p-defer": { - "version": "1.0.0", + "node_modules/chalk-template": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.2.tgz", + "integrity": "sha512-2bxTP2yUH7AJj/VAXfcA+4IcWGdQ87HwBANLt5XxGTeomo8yG0y95N1um9i5StvhT/Bl0/2cARA5v1PpPXUxUA==", "dev": true, "license": "MIT", + "dependencies": { + "chalk": "^5.2.0" + }, "engines": { - "node": ">=4" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" } }, - "node_modules/p-event": { - "version": "5.0.1", + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", "dependencies": { - "p-timeout": "^5.0.2" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 8.10.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/p-filter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", - "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { - "p-map": "^2.0.0" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/p-filter/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "dev": true, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=6" + "node": ">=18" } }, - "node_modules/p-finally": { - "version": "1.0.0", + "node_modules/chunkd": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", + "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/p-limit": { - "version": "2.3.0", + "node_modules/ci-parallel-vars": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz", + "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-map": { - "version": "5.5.0", + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "license": "MIT", - "dependencies": { - "aggregate-error": "^4.0.0" - }, "engines": { - "node": ">=12" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-queue": { - "version": "6.6.2", + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, "license": "MIT", "dependencies": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-queue/node_modules/eventemitter3": { - "version": "4.0.7", - "license": "MIT" - }, - "node_modules/p-queue/node_modules/p-timeout": { - "version": "3.2.0", - "license": "MIT", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", "dependencies": { - "p-finally": "^1.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-timeout": { - "version": "5.1.0", - "dev": true, - "license": "MIT", "engines": { "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/pac-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", - "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.5", - "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.4" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 14" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", - "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, - "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" - }, + "license": "MIT" + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 14" + "node": ">=8" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true - }, - "node_modules/package-manager-detector": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.0.tgz", - "integrity": "sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==", - "dev": true - }, - "node_modules/parent-module": { - "version": "1.0.1", + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { - "callsites": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/parent-module/node_modules/callsites": { - "version": "3.1.0", + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/parse-json": { - "version": "5.2.0", + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/parse-ms": { - "version": "3.0.0", + "node_modules/code-excerpt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "convert-to-spaces": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/parse-srcset": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/parse-svg-path": { - "version": "0.1.2", - "license": "MIT" + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } }, - "node_modules/parse5": { - "version": "6.0.1", - "dev": true, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/parseurl": { - "version": "1.3.3", + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, "engines": { "node": ">= 0.8" } }, - "node_modules/path-equal": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz", - "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==" + "node_modules/comlink": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/comlink/-/comlink-4.4.2.tgz", + "integrity": "sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==", + "license": "Apache-2.0" }, - "node_modules/path-exists": { - "version": "4.0.0", + "node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "license": "(WTFPL OR MIT)" + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true, + "license": "ISC" }, - "node_modules/path-key": { - "version": "3.1.1", + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "dev": true, - "license": "BlueOak-1.0.0", + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" }, "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 0.8.0" } }, - "node_modules/path-to-regexp": { - "version": "2.2.1", - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "dev": true, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true - }, - "node_modules/pathval": { + "node_modules/compression/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "dev": true, - "engines": { - "node": ">= 14.16" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, - "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "optional": true, - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "node_modules/concordance": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", + "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", "dev": true, + "license": "ISC", + "dependencies": { + "date-time": "^3.1.0", + "esutils": "^2.0.3", + "fast-diff": "^1.2.0", + "js-string-escape": "^1.0.1", + "lodash": "^4.17.15", + "md5-hex": "^3.0.1", + "semver": "^7.3.2", + "well-known-symbols": "^2.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" } }, - "node_modules/pirates": { - "version": "4.0.6", + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">= 6" - } - }, - "node_modules/pixi.js": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.4.1.tgz", - "integrity": "sha512-3ZbEIkLYYi602UB5wuN7kPz3VsGHoJa6nxD8ustvMLRySxHAR9Z8tCAYY8ISgNplpPbaDw03B0yTD4/k9f6cAQ==", - "dependencies": { - "@pixi/colord": "^2.9.6", - "@types/css-font-loading-module": "^0.0.12", - "@types/earcut": "^2.1.4", - "@webgpu/types": "^0.1.40", - "@xmldom/xmldom": "^0.8.10", - "earcut": "^2.2.4", - "eventemitter3": "^5.0.1", - "ismobilejs": "^1.1.1", - "parse-svg-path": "^0.1.2" + "node": "^14.18.0 || >=16.10.0" } }, - "node_modules/pkg-conf": { - "version": "4.0.0", - "dev": true, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "license": "MIT", "dependencies": { - "find-up": "^6.0.0", - "load-json-file": "^7.0.0" + "safe-buffer": "5.2.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/pkg-conf/node_modules/find-up": { - "version": "6.3.0", - "dev": true, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "license": "MIT", - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/pkg-conf/node_modules/locate-path": { - "version": "7.2.0", + "node_modules/convert-to-spaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^6.0.0" - }, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-conf/node_modules/p-limit": { - "version": "4.0.0", - "dev": true, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", - "dependencies": { - "yocto-queue": "^1.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/pkg-conf/node_modules/p-locate": { - "version": "6.0.0", - "dev": true, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", "license": "MIT", "dependencies": { - "p-limit": "^4.0.0" + "cookie": "0.7.2", + "cookie-signature": "1.0.6" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/core-js-pure": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.47.0.tgz", + "integrity": "sha512-BcxeDbzUrRnXGYIVAGFtcGQVNpFcUhVjr6W7F8XktvQW2iJP9e66GP6xdKotCRFlrxBvNIBrhwKteRXqMV86Nw==", + "hasInstallScript": true, + "license": "MIT", "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/core-js" } }, - "node_modules/pkg-conf/node_modules/path-exists": { - "version": "5.0.0", - "dev": true, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 0.10" } }, - "node_modules/pkg-conf/node_modules/yocto-queue": { - "version": "1.0.0", + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, "engines": { - "node": ">=12.20" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "dev": true, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", - "peer": true, "dependencies": { - "find-up": "^4.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/please-upgrade-node": { - "version": "3.2.0", + "node_modules/css-tree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", "dev": true, "license": "MIT", "dependencies": { - "semver-compare": "^1.0.0" + "mdn-data": "2.12.2", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, - "node_modules/plur": { - "version": "5.1.0", + "node_modules/cssstyle": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.4.tgz", + "integrity": "sha512-KyOS/kJMEq5O9GdPnaf82noigg5X5DYn0kZPJTaAsCUaBizp6Xa1y9D4Qoqf/JazEXWuruErHgVXwjN5391ZJw==", "dev": true, "license": "MIT", "dependencies": { - "irregular-plurals": "^3.3.0" + "@asamuzakjp/css-color": "^4.1.0", + "@csstools/css-syntax-patches-for-csstree": "1.0.14", + "css-tree": "^3.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=20" } }, - "node_modules/portfinder": { - "version": "1.0.32", + "node_modules/currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", "dev": true, "license": "MIT", "dependencies": { - "async": "^2.6.4", - "debug": "^3.2.7", - "mkdirp": "^0.5.6" + "array-find-index": "^1.0.1" }, "engines": { - "node": ">= 0.12.0" + "node": ">=0.10.0" } }, - "node_modules/portfinder/node_modules/async": { - "version": "2.6.4", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.14" - } + "node_modules/d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==", + "license": "BSD-3-Clause" }, - "node_modules/portfinder/node_modules/debug": { - "version": "3.2.7", - "dev": true, + "node_modules/d3-polygon": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", + "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==", + "license": "BSD-3-Clause" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "license": "MIT", - "dependencies": { - "ms": "^2.1.1" + "engines": { + "node": ">= 12" } }, - "node_modules/portfinder/node_modules/mkdirp": { - "version": "0.5.6", + "node_modules/data-urls": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.0.tgz", + "integrity": "sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==", "dev": true, "license": "MIT", "dependencies": { - "minimist": "^1.2.6" + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^15.0.0" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": ">=20" } }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", + "node_modules/data-urls/node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, "engines": { - "node": ">= 0.4" + "node": ">=20" } }, - "node_modules/postcss": { - "version": "8.4.45", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz", - "integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" - }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz", + "integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=20" } }, - "node_modules/posthtml": { - "version": "0.16.6", + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", + "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", "dev": true, "license": "MIT", "dependencies": { - "posthtml-parser": "^0.11.0", - "posthtml-render": "^3.0.0" + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=20" } }, - "node_modules/posthtml-parser": { - "version": "0.11.0", + "node_modules/date-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", + "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", "dev": true, "license": "MIT", "dependencies": { - "htmlparser2": "^7.1.1" + "time-zone": "^1.0.0" }, "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/posthtml-parser/node_modules/dom-serializer": { - "version": "1.4.1", - "dev": true, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "ms": "^2.1.3" }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/posthtml-parser/node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", "dev": true, - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } + "license": "MIT" }, - "node_modules/posthtml-parser/node_modules/domhandler": { - "version": "4.3.1", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.2.0" - }, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "node": ">=0.4.0" } }, - "node_modules/posthtml-parser/node_modules/domutils": { - "version": "2.8.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" } }, - "node_modules/posthtml-parser/node_modules/entities": { - "version": "3.0.1", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/posthtml-parser/node_modules/htmlparser2": { - "version": "7.2.0", + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.2", - "domutils": "^2.8.0", - "entities": "^3.0.1" + "license": "Apache-2.0", + "engines": { + "node": ">=8" } }, - "node_modules/posthtml-render": { + "node_modules/doctrine": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "is-json": "^2.0.1" + "esutils": "^2.0.2" }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/posthtml-urls": { - "version": "1.0.0", - "dev": true, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { - "http-equiv-refresh": "^1.0.0", - "list-to-array": "^1.1.0", - "parse-srcset": "^1.0.2", - "promise-each": "^2.2.0" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">= 4" + "node": ">= 0.4" } }, - "node_modules/prebuild-install": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", - "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "node_modules/duplexify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", "license": "MIT", "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=10" + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.2" } }, - "node_modules/prebuild-install/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "node_modules/earcut": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", + "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", "license": "ISC" }, - "node_modules/prebuild-install/node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "license": "MIT", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" + "safe-buffer": "^5.0.1" } }, - "node_modules/prebuild-install/node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/effect": { + "version": "3.19.4", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.19.4.tgz", + "integrity": "sha512-gApFffMwpDVgmw/FzCaYWt6zw4m0xAnQf5+cPS0+Sl85AxfeovJeEIsiEQVlk+ZvtBYcoPXxi65GIyruzanQ5g==", + "dev": true, "license": "MIT", "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", + "node_modules/emittery": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-1.2.0.tgz", + "integrity": "sha512-KxdRyyFcS85pH3dnU8Y5yFUm2YJdaHwcBZWrfG8o89ZY9a13/f9itbN+YG3ELbBo9Pg5zvIozstmuV8bX13q6g==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/pretty-format": { - "version": "29.7.0", + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", - "peer": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.8" } }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "dev": true, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "dependencies": { + "once": "^1.4.0" } }, - "node_modules/pretty-ms": { - "version": "8.0.0", + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "license": "MIT", "dependencies": { - "parse-ms": "^3.0.0" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8.6" } }, - "node_modules/prismjs": { - "version": "1.29.0", + "node_modules/enquirer/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/proc-log": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", - "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "node_modules/enquirer/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", "engines": { - "node": ">=0.4.0" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/promise": { - "version": "7.3.1", + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "license": "MIT", - "dependencies": { - "asap": "~2.0.3" + "engines": { + "node": ">=6" } }, - "node_modules/promise-each": { - "version": "2.2.0", + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { - "any-promise": "^0.1.0" + "is-arrayish": "^0.2.1" } }, - "node_modules/prompts": { - "version": "2.4.2", - "dev": true, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, "engines": { - "node": ">= 6" + "node": ">= 0.4" } }, - "node_modules/proper-lockfile": { - "version": "4.1.2", - "dev": true, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "retry": "^0.12.0", - "signal-exit": "^3.0.2" - } - }, - "node_modules/proto3-json-serializer": { - "version": "2.0.1", - "license": "Apache-2.0", - "dependencies": { - "protobufjs": "^7.2.5" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/protobufjs": { - "version": "7.2.6", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, "engines": { - "node": ">=12.0.0" + "node": ">= 0.4" } }, - "node_modules/proxy-addr": { - "version": "2.0.7", + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "es-errors": "^1.3.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 0.4" } }, - "node_modules/proxy-agent": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", - "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", - "dev": true, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.3", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">= 14" + "node": ">= 0.4" } }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "node_modules/prr": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "license": "ISC" - }, - "node_modules/psl": { - "version": "1.9.0", - "dev": true, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "license": "MIT" }, - "node_modules/pug": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.3.tgz", - "integrity": "sha512-uBi6kmc9f3SZ3PXxqcHiUZLmIXgfgWooKWXcwSGwQd2Zi5Rb0bT14+8CJjJgI8AB+nndLaNgHGrcc6bPIB665g==", - "dev": true, - "dependencies": { - "pug-code-gen": "^3.0.3", - "pug-filters": "^4.0.0", - "pug-lexer": "^5.0.1", - "pug-linker": "^4.0.0", - "pug-load": "^3.0.0", - "pug-parser": "^6.0.0", - "pug-runtime": "^3.0.1", - "pug-strip-comments": "^2.0.0" - } - }, - "node_modules/pug-attrs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", - "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, - "dependencies": { - "constantinople": "^4.0.1", - "js-stringify": "^1.0.2", - "pug-runtime": "^3.0.0" + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pug-code-gen": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.3.tgz", - "integrity": "sha512-cYQg0JW0w32Ux+XTeZnBEeuWrAY7/HNE6TWnhiHGnnRYlCgyAUPoyh9KzCMa9WhcJlJ1AtQqpEYHc+vbCzA+Aw==", + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { - "constantinople": "^4.0.1", - "doctypes": "^1.1.0", - "js-stringify": "^1.0.2", - "pug-attrs": "^3.0.0", - "pug-error": "^2.1.0", - "pug-runtime": "^3.0.1", - "void-elements": "^3.1.0", - "with": "^7.0.0" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/pug-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.1.0.tgz", - "integrity": "sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==", - "dev": true - }, - "node_modules/pug-filters": { - "version": "4.0.0", + "node_modules/eslint-plugin-expect-type": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-expect-type/-/eslint-plugin-expect-type-0.6.2.tgz", + "integrity": "sha512-XWgtpplzr6GlpPUFG9ZApnSTv7QJXAPNN6hNmrlleVVCkAK23f/3E2BiCoA3Xtb0rIKfVKh7TLe+D1tcGt8/1w==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "constantinople": "^4.0.1", - "jstransformer": "1.0.0", - "pug-error": "^2.0.0", - "pug-walk": "^2.0.0", - "resolve": "^1.15.1" + "@typescript-eslint/utils": "^6.10.0 || ^7.0.1 || ^8", + "fs-extra": "^11.1.1", + "get-tsconfig": "^4.8.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@typescript-eslint/parser": ">=6", + "eslint": ">=7", + "typescript": ">=4" } }, - "node_modules/pug-lexer": { - "version": "5.0.1", + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "character-parser": "^2.2.0", - "is-expression": "^4.0.0", - "pug-error": "^2.0.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/pug-linker": { - "version": "4.0.0", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "MIT", - "dependencies": { - "pug-error": "^2.0.0", - "pug-walk": "^2.0.0" + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/pug-load": { - "version": "3.0.0", + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "dependencies": { - "object-assign": "^4.1.1", - "pug-walk": "^2.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/pug-parser": { - "version": "6.0.0", + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { - "pug-error": "^2.0.0", - "token-stream": "1.0.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/pug-runtime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", - "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==", - "dev": true - }, - "node_modules/pug-strip-comments": { - "version": "2.0.0", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { - "pug-error": "^2.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/pug-walk": { - "version": "2.0.0", + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT" - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "license": "MIT", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/punycode": { - "version": "1.4.1", - "license": "MIT" - }, - "node_modules/punycode.js": { - "version": "2.3.1", + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 4" } }, - "node_modules/puppeteer-core": { - "version": "23.3.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.3.0.tgz", - "integrity": "sha512-sB2SsVMFs4gKad5OCdv6w5vocvtEUrRl0zQqSyRPbo/cj1Ktbarmhxy02Zyb9R9HrssBcJDZbkrvBnbaesPyYg==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "@puppeteer/browsers": "2.4.0", - "chromium-bidi": "0.6.5", - "debug": "^4.3.6", - "devtools-protocol": "0.0.1330662", - "typed-query-selector": "^2.12.0", - "ws": "^8.18.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/pure-rand": { - "version": "6.1.0", + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/pyodide": { - "version": "0.26.2", - "resolved": "https://registry.npmjs.org/pyodide/-/pyodide-0.26.2.tgz", - "integrity": "sha512-8VCRdFX83gBsWs6XP2rhG8HMaB+JaVyyav4q/EMzoV8fXH8HN6T5IISC92SNma6i1DRA3SVXA61S1rJcB8efgA==", + "license": "MIT", "dependencies": { - "ws": "^8.5.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=18.0.0" + "node": ">=8" } }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "side-channel": "^1.0.6" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=0.6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/queue-tick": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", - "dev": true + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } }, - "node_modules/randombytes": { - "version": "2.1.0", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.0", - "license": "MIT", + "estraverse": "^5.1.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=0.10" } }, - "node_modules/raw-body": { - "version": "2.5.2", - "license": "MIT", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 0.8" + "node": ">=4.0" } }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "license": "MIT", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">= 0.8" + "node": ">=4.0" } }, - "node_modules/rc": { - "version": "1.2.8", - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "license": "MIT", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/react-is": { - "version": "18.2.0", - "dev": true, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "license": "MIT", - "peer": true + "engines": { + "node": ">= 0.6" + } }, - "node_modules/read-yaml-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-1.1.0.tgz", - "integrity": "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.5", - "js-yaml": "^3.6.1", - "pify": "^4.0.1", - "strip-bom": "^3.0.0" - }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/readable-stream": { - "version": "3.6.2", + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "eventsource-parser": "^3.0.1" }, "engines": { - "node": ">= 6" + "node": ">=18.0.0" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "dev": true, + "node_modules/eventsource-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, "engines": { - "node": ">=8.10.0" + "node": ">=18.0.0" } }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/execa": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.0.tgz", + "integrity": "sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==", "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.6", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^8.0.1", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^6.0.0", + "pretty-ms": "^9.2.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.1.1" + }, "engines": { - "node": ">=8.6" + "node": "^18.19.0 || >=20.5.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/recursive-copy": { - "version": "2.0.14", - "dev": true, - "license": "ISC", - "dependencies": { - "errno": "^0.1.2", - "graceful-fs": "^4.1.4", - "junk": "^1.0.1", - "maximatch": "^0.1.0", - "mkdirp": "^0.5.1", - "pify": "^2.3.0", - "promise": "^7.0.1", - "rimraf": "^2.7.1", - "slash": "^1.0.0" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/recursive-copy/node_modules/brace-expansion": { - "version": "1.1.11", + "node_modules/execa/node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/recursive-copy/node_modules/glob": { - "version": "7.2.3", - "dev": true, - "license": "ISC", + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "engines": { - "node": "*" + "node": ">= 0.10.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/recursive-copy/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/recursive-copy/node_modules/mkdirp": { - "version": "0.5.6", - "dev": true, + "node_modules/express-rate-limit": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", + "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" + "engines": { + "node": ">= 16" }, - "bin": { - "mkdirp": "bin/cmd.js" + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" } }, - "node_modules/recursive-copy/node_modules/pify": { - "version": "2.3.0", - "dev": true, + "node_modules/express-static-gzip": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.2.0.tgz", + "integrity": "sha512-4ZQ0pHX0CAauxmzry2/8XFLM6aZA4NBvg9QezSlsEO1zLnl7vMFa48/WIcjzdfOiEUS4S1npPPKP2NHHYAp6qg==", "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/recursive-copy/node_modules/rimraf": { - "version": "2.7.1", - "dev": true, - "license": "ISC", "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "parseurl": "^1.3.3", + "serve-static": "^1.16.2" } }, - "node_modules/recursive-copy/node_modules/slash": { - "version": "1.0.0", - "dev": true, + "node_modules/express/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/redeyed": { - "version": "2.1.1", - "dev": true, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "esprima": "~4.0.0" + "ms": "2.0.0" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "pure-rand": "^6.1.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.0.0" } }, - "node_modules/registry-auth-token": { - "version": "3.3.2", - "license": "MIT", - "dependencies": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" }, - "node_modules/registry-url": { - "version": "3.1.0", + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, "license": "MIT", "dependencies": { - "rc": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, "engines": { - "node": ">= 6" + "node": ">=8.6.0" } }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "is-glob": "^4.0.1" }, "engines": { - "node": ">= 0.12" + "node": ">= 6" } }, - "node_modules/request/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, - "engines": { - "node": ">=0.6" - } + "license": "MIT" }, - "node_modules/request/node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fast-xml-parser": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", + "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "strnum": "^1.1.1" }, - "engines": { - "node": ">=0.8" + "bin": { + "fxparser": "src/cli/cli.js" } }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, - "bin": { - "uuid": "bin/uuid" + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/require-directory": { - "version": "2.1.1", + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/require-from-string": { - "version": "2.0.2", + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, "engines": { - "node": ">=0.10.0" + "node": "^12.20 || >= 14.13" } }, - "node_modules/resolve": { - "version": "1.22.8", + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "is-unicode-supported": "^2.0.0" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "license": "MIT", "dependencies": { - "resolve-from": "^5.0.0" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">=8" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/resolve-from": { - "version": "5.0.0", + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { "node": ">=8" } }, - "node_modules/resolve-path": { - "version": "1.4.0", + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { - "http-errors": "~1.6.2", - "path-is-absolute": "1.0.1" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" }, - "engines": { - "node": ">= 0.8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/resolve-path/node_modules/depd": { - "version": "1.1.2", + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/resolve-path/node_modules/http-errors": { - "version": "1.6.3", + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "license": "MIT", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" }, "engines": { - "node": ">= 0.6" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/resolve-path/node_modules/inherits": { - "version": "2.0.3", - "dev": true, - "license": "ISC" - }, - "node_modules/resolve-path/node_modules/setprototypeof": { - "version": "1.1.0", + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, "license": "ISC" }, - "node_modules/resolve-path/node_modules/statuses": { - "version": "1.5.0", - "dev": true, + "node_modules/flubber": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/flubber/-/flubber-0.4.2.tgz", + "integrity": "sha512-79RkJe3rA4nvRCVc2uXjj7U/BAUq84TS3KHn6c0Hr9K64vhj83ZNLUziNx4pJoBumSPhOl5VjH+Z0uhi+eE8Uw==", "license": "MIT", - "engines": { - "node": ">= 0.6" + "dependencies": { + "d3-array": "^1.2.0", + "d3-polygon": "^1.0.3", + "earcut": "^2.1.1", + "svg-path-properties": "^0.2.1", + "svgpath": "^2.2.1", + "topojson-client": "^3.0.0" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "dev": true, - "license": "MIT", + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/resolve.exports": { - "version": "2.0.2", - "dev": true, + "node_modules/form-data": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", "license": "MIT", - "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" + }, "engines": { - "node": ">=10" + "node": ">= 0.12" } }, - "node_modules/restore-cursor": { - "version": "4.0.0", - "dev": true, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "fetch-blob": "^3.1.2" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12.20.0" } }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "dev": true, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.6" } }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", "dev": true, "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=14.14" } }, - "node_modules/retry": { - "version": "0.12.0", + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 4" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/retry-request": { - "version": "7.0.2", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", + "license": "Apache-2.0", "dependencies": { - "@types/request": "^2.48.8", "extend": "^3.0.2", - "teeny-request": "^9.0.0" + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" }, "engines": { "node": ">=14" } }, - "node_modules/reusify": { - "version": "1.0.4", - "dev": true, + "node_modules/gaxios/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "license": "MIT", "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", - "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", - "dev": true, - "dependencies": { - "glob": "^11.0.0", - "package-json-from-dist": "^1.0.0" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, + "node_modules/gaxios/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "uuid": "dist/bin/uuid" } }, - "node_modules/rimraf/node_modules/jackspeak": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", - "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", - "dev": true, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/rimraf/node_modules/lru-cache": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", - "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", - "dev": true, "engines": { - "node": "20 || >=22" + "node": ">=18" } }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "dev": true, + "node_modules/gcp-metadata/node_modules/gaxios": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", + "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "license": "Apache-2.0", "dependencies": { - "brace-expansion": "^2.0.1" + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=18" } }, - "node_modules/rimraf/node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "dev": true, + "node_modules/gcp-metadata/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, "engines": { - "node": "20 || >=22" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, - "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "node_modules/gcp-metadata/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", "dependencies": { - "@types/estree": "1.0.5" + "glob": "^10.3.7" }, "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "rimraf": "dist/esm/bin.mjs" }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", - "fsevents": "~2.3.2" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rollup-plugin-dts": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.1.1.tgz", - "integrity": "sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "dependencies": { - "magic-string": "^0.30.10" - }, + "license": "ISC", "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/Swatinem" - }, - "optionalDependencies": { - "@babel/code-frame": "^7.24.2" - }, - "peerDependencies": { - "rollup": "^3.29.4 || ^4", - "typescript": "^4.5 || ^5.0" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/rrweb-cssom": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", - "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", - "dev": true - }, - "node_modules/run-parallel": { - "version": "1.2.0", + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "dev": true, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { - "node": ">=0.4" + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } }, - "node_modules/safe-regex-test": { - "version": "1.0.3", + "node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/safe-stable-stringify": { - "version": "2.4.3", + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "devOptional": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "license": "MIT" + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/saxes": { - "version": "6.0.0", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", "dependencies": { - "xmlchars": "^2.2.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=v12.22.7" + "node": ">=10.13.0" } }, - "node_modules/section-matter": { - "version": "1.0.0", + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "license": "MIT", "dependencies": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.0" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semver-compare": { - "version": "1.0.0", - "dev": true, - "license": "MIT" + "node_modules/google-auth-library": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz", + "integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^8.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", + "node_modules/google-auth-library/node_modules/gaxios": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", + "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "license": "Apache-2.0", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=18" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/google-auth-library/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "license": "MIT", "dependencies": { - "ms": "2.0.0" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", + "node_modules/google-auth-library/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, "bin": { - "mime": "cli.js" + "rimraf": "dist/esm/bin.mjs" }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", "engines": { - "node": ">=4" + "node": ">=14" } }, - "node_modules/send/node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serialize-error": { - "version": "7.0.1", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/gtoken": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", + "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", "license": "MIT", "dependencies": { - "type-fest": "^0.13.1" + "gaxios": "^7.0.0", + "jws": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" + "node_modules/gtoken/node_modules/gaxios": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", + "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=18" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/gtoken/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", "dependencies": { - "randombytes": "^2.1.0" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" } }, - "node_modules/serve": { - "version": "14.2.3", - "license": "MIT", + "node_modules/gtoken/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", "dependencies": { - "@zeit/schemas": "2.36.0", - "ajv": "8.12.0", - "arg": "5.0.2", - "boxen": "7.0.0", - "chalk": "5.0.1", - "chalk-template": "0.4.0", - "clipboardy": "3.0.0", - "compression": "1.7.4", - "is-port-reachable": "4.0.0", - "serve-handler": "6.1.5", - "update-check": "1.5.4" + "glob": "^10.3.7" }, "bin": { - "serve": "build/main.js" + "rimraf": "dist/esm/bin.mjs" }, - "engines": { - "node": ">= 14" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/serve-handler": { - "version": "6.1.5", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "license": "MIT", - "dependencies": { - "bytes": "3.0.0", - "content-disposition": "0.5.2", - "fast-url-parser": "1.1.3", - "mime-types": "2.1.18", - "minimatch": "3.1.2", - "path-is-inside": "1.0.2", - "path-to-regexp": "2.2.1", - "range-parser": "1.2.0" + "engines": { + "node": ">=8" } }, - "node_modules/serve-handler/node_modules/brace-expansion": { - "version": "1.1.11", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serve-handler/node_modules/mime-db": { - "version": "1.33.0", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serve-handler/node_modules/mime-types": { - "version": "2.1.18", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { - "mime-db": "~1.33.0" + "function-bind": "^1.1.2" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" } }, - "node_modules/serve-handler/node_modules/minimatch": { - "version": "3.1.2", + "node_modules/hosted-git-info": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", + "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", + "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "lru-cache": "^10.0.1" }, "engines": { - "node": "*" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, "license": "MIT", "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" + "whatwg-encoding": "^3.1.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=18" } }, - "node_modules/serve-static/node_modules/encodeurl": { + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, + "node_modules/http-errors": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, "engines": { "node": ">= 0.8" } }, - "node_modules/serve/node_modules/ajv": { - "version": "8.12.0", + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">= 14" } }, - "node_modules/serve/node_modules/chalk": { - "version": "5.0.1", + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "engines": { + "node": ">= 14" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "node_modules/human-signals": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", + "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", "dev": true, - "optional": true + "license": "Apache-2.0", + "optional": true, + "peer": true, + "engines": { + "node": ">=18.18.0" + } }, - "node_modules/set-function-length": { - "version": "1.2.2", + "node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/set-function-name": { - "version": "2.0.2", + "node_modules/idb": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/idb/-/idb-8.0.3.tgz", + "integrity": "sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==", + "license": "ISC" + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">= 4" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "license": "ISC" + "node_modules/ignore-by-default": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.1.0.tgz", + "integrity": "sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10 <11 || >=12 <13 || >=14" + } }, - "node_modules/shebang-command": { - "version": "2.0.0", + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/side-channel": { - "version": "1.0.6", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, "engines": { - "node": ">= 0.4" + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } }, - "node_modules/signal-exit": { - "version": "3.0.7", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/irregular-plurals": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", + "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", + "dev": true, "license": "MIT", - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/sisteransi": { - "version": "1.0.5", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, "license": "MIT" }, - "node_modules/skin-tone": { - "version": "2.0.0", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", "dependencies": { - "unicode-emoji-modifier-base": "^1.0.0" + "binary-extensions": "^2.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/slash": { - "version": "3.0.0", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/slice-ansi": { - "version": "5.0.0", + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { - "node": "*" + "node": ">=0.12.0" } }, - "node_modules/slugify": { - "version": "1.6.6", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true, + "license": "MIT", + "optional": true, + "peer": true, "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/smob": { - "version": "1.5.0", - "dev": true, - "license": "MIT" - }, - "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, + "license": "MIT", "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" + "node": ">=0.10.0" } }, - "node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true, - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } + "license": "MIT" }, - "node_modules/source-map": { - "version": "0.6.1", - "devOptional": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" }, - "node_modules/source-map-js": { - "version": "1.2.0", - "license": "BSD-3-Clause", + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "devOptional": true, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/spawndamnit": { + "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawndamnit/-/spawndamnit-2.0.0.tgz", - "integrity": "sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==", - "dev": true, - "dependencies": { - "cross-spawn": "^5.1.0", - "signal-exit": "^3.0.2" - } + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" }, - "node_modules/spawndamnit/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dev": true, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/spawndamnit/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } + "node_modules/js-base64": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.8.tgz", + "integrity": "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==", + "license": "BSD-3-Clause" }, - "node_modules/spawndamnit/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "node_modules/js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/spawndamnit/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/spawndamnit/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" + "argparse": "^2.0.1" }, "bin": { - "which": "bin/which" + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/spawndamnit/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "node_modules/jsdom": { + "version": "27.3.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.3.0.tgz", + "integrity": "sha512-GtldT42B8+jefDUC4yUKAvsaOrH7PDHmZxZXNgF2xMmymjUbRYJvpAybZAKEmXDGTM0mCsz8duOa4vTm5AY2Kg==", "dev": true, + "license": "MIT", "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "@acemir/cssom": "^0.9.28", + "@asamuzakjp/dom-selector": "^6.7.6", + "cssstyle": "^5.3.4", + "data-urls": "^6.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "parse5": "^8.0.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^15.1.0", + "ws": "^8.18.3", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/jsdom/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", - "dev": true - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "node_modules/jsdom/node_modules/parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", "dev": true, + "license": "MIT", "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "entities": "^6.0.0" }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/ssri": { - "version": "8.0.1", + "node_modules/jsdom/node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "minipass": "^3.1.1" + "punycode": "^2.3.1" }, "engines": { - "node": ">= 8" + "node": ">=20" } }, - "node_modules/ssri/node_modules/minipass": { - "version": "3.3.6", + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz", + "integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==", "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">=8" + "node": ">=20" } }, - "node_modules/stack-utils": { - "version": "2.0.6", + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", + "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", "dev": true, "license": "MIT", "dependencies": { - "escape-string-regexp": "^2.0.0" + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.0" }, "engines": { - "node": ">=10" + "node": ">=20" } }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "dev": true, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "bignumber.js": "^9.0.0" } }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" }, - "node_modules/statuses": { - "version": "2.0.1", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" }, - "node_modules/std-env": { - "version": "3.7.0", + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, - "node_modules/stdin-discarder": { - "version": "0.2.2", + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "universalify": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/stream-events": { - "version": "1.0.5", + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", "license": "MIT", "dependencies": { - "stubs": "^3.0.0" + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" } }, - "node_modules/stream-read-all": { - "version": "3.0.1", - "dev": true, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/stream-shift": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/streamx": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", - "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { - "fast-fifo": "^1.3.2", - "queue-tick": "^1.0.1", - "text-decoder": "^1.1.0" - }, - "optionalDependencies": { - "bare-events": "^2.2.0" + "json-buffer": "3.0.1" } }, - "node_modules/string_decoder": { - "version": "1.3.0", + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" + "engines": { + "node": ">=6" } }, - "node_modules/string-length": { - "version": "4.0.2", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">=10" + "node": ">= 0.8.0" } }, - "node_modules/string-length/node_modules/ansi-regex": { - "version": "5.0.1", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true, + "license": "MIT" + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" + "dependencies": { + "uc.micro": "^2.0.0" } }, - "node_modules/string-length/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "peer": true, + "node_modules/lit": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.1.tgz", + "integrity": "sha512-Ksr/8L3PTapbdXJCk+EJVB78jDodUMaP54gD24W186zGRARvwrsPfS60wae/SSCTCNZVPd1chXqio1qHQmu4NA==", + "license": "BSD-3-Clause", "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "@lit/reactive-element": "^2.1.0", + "lit-element": "^4.2.0", + "lit-html": "^3.3.0" } }, - "node_modules/string-replace-async": { - "version": "3.0.2", - "license": "MIT", - "engines": { - "node": ">= 14.0.0" + "node_modules/lit-element": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.1.tgz", + "integrity": "sha512-WGAWRGzirAgyphK2urmYOV72tlvnxw7YfyLDgQ+OZnM9vQQBQnumQ7jUJe6unEzwGU3ahFOjuz1iz1jjrpCPuw==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.4.0", + "@lit/reactive-element": "^2.1.0", + "lit-html": "^3.3.0" } }, - "node_modules/string-to-template-literal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string-to-template-literal/-/string-to-template-literal-2.0.0.tgz", - "integrity": "sha512-AbTUWHXMyoRlTFP9qe013dfGTFq1XbcBLUoLC7PcumbJewtUwNXCvnko5cH2gZkUFC7kD2Fwxiv4YIndkU0xHA==", - "dev": true, - "engines": { - "node": ">=12.0.0" + "node_modules/lit-html": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.1.tgz", + "integrity": "sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA==", + "license": "BSD-3-Clause", + "dependencies": { + "@types/trusted-types": "^2.0.2" } }, - "node_modules/string-width": { - "version": "5.1.2", + "node_modules/littlezipper": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/littlezipper/-/littlezipper-0.1.5.tgz", + "integrity": "sha512-6DrzicMgPrg53T2ycFNS1bN3/6aHYUmzPxMArCgoyUCeThjE3k5+jYmvhxAeUwVNu9FIjjEkAPerSTipv2Ro8w==", + "license": "MIT" + }, + "node_modules/load-json-file": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", + "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", + "dev": true, "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, "engines": { - "node": ">=12" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true, "license": "MIT" }, - "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "dev": true, + "node_modules/logic": { + "resolved": "experiments/logic", + "link": true + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "dev": true, + "node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "bin": { + "marked": "bin/marked.js" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 20" } }, - "node_modules/strip-ansi": { - "version": "7.1.0", + "node_modules/matcher": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", + "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", + "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "escape-string-regexp": "^5.0.0" }, "engines": { - "node": ">=12" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", + "node_modules/matcher/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/strip-bom": { - "version": "3.0.0", + "node_modules/md5-hex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", + "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", "dev": true, "license": "MIT", + "dependencies": { + "blueimp-md5": "^2.10.0" + }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/strip-bom-string": { - "version": "1.0.0", + "node_modules/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", "dev": true, + "license": "CC0-1.0" + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/strip-final-newline": { - "version": "3.0.0", + "node_modules/memoize": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/memoize/-/memoize-10.2.0.tgz", + "integrity": "sha512-DeC6b7QBrZsRs3Y02A6A7lQyzFbsQbqgjI6UW0GigGWV+u1s25TycMr0XHZE4cJce7rY/vyw2ctMQqfDkIhUEA==", "dev": true, "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.1" + }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sindresorhus/memoize?sponsor=1" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "license": "MIT", - "engines": { - "node": ">=8" - }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strnum": { - "version": "1.0.5", - "license": "MIT", - "optional": true - }, - "node_modules/stubs": { - "version": "3.0.0", - "license": "MIT" - }, - "node_modules/style-mod": { - "version": "4.1.2", - "license": "MIT" - }, - "node_modules/supertap": { - "version": "3.0.1", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "license": "MIT", - "dependencies": { - "indent-string": "^5.0.0", - "js-yaml": "^3.14.1", - "serialize-error": "^7.0.1", - "strip-ansi": "^7.0.1" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 8" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "dev": true, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">= 0.6" } }, - "node_modules/supports-hyperlinks": { - "version": "3.0.0", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=14.18" + "node": ">=8.6" } }, - "node_modules/supports-hyperlinks/node_modules/has-flag": { - "version": "4.0.0", + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/supports-hyperlinks/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, + "node_modules/mime": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.1.0.tgz", + "integrity": "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==", + "funding": [ + "https://github.com/sponsors/broofa" + ], "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" + "bin": { + "mime": "bin/cli.js" }, "engines": { - "node": ">=8" + "node": ">=16" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.6" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "dev": true, - "license": "MIT" - }, - "node_modules/syncpack": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/syncpack/-/syncpack-13.0.0.tgz", - "integrity": "sha512-0PIoEWMP2+YkllkcZXw8N9d2sFqpmr8ULBdvms3gc1vG5tnccEMqc6flxHYnF/N+NTTcUnf0J+4xAD5hwH6XGQ==", - "dev": true, - "dependencies": { - "@effect/schema": "0.71.1", - "chalk": "5.3.0", - "chalk-template": "1.1.0", - "commander": "12.1.0", - "cosmiconfig": "9.0.0", - "effect": "3.6.5", - "enquirer": "2.4.1", - "fast-check": "3.21.0", - "globby": "14.0.2", - "jsonc-parser": "3.3.1", - "minimatch": "9.0.5", - "npm-package-arg": "11.0.3", - "ora": "8.0.1", - "prompts": "2.4.2", - "read-yaml-file": "2.1.0", - "semver": "7.6.3", - "tightrope": "0.2.0", - "ts-toolbelt": "9.6.0" - }, - "bin": { - "syncpack": "dist/bin.js", - "syncpack-fix-mismatches": "dist/bin-fix-mismatches/index.js", - "syncpack-format": "dist/bin-format/index.js", - "syncpack-lint": "dist/bin-lint/index.js", - "syncpack-lint-semver-ranges": "dist/bin-lint-semver-ranges/index.js", - "syncpack-list": "dist/bin-list/index.js", - "syncpack-list-mismatches": "dist/bin-list-mismatches/index.js", - "syncpack-prompt": "dist/bin-prompt/index.js", - "syncpack-set-semver-ranges": "dist/bin-set-semver-ranges/index.js", - "syncpack-update": "dist/bin-update/index.js" + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" }, "engines": { - "node": ">=18.18.0" + "node": ">= 0.6" } }, - "node_modules/syncpack/node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/syncpack/node_modules/chalk": { - "version": "5.3.0", - "dev": true, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">= 0.6" + } + }, + "node_modules/mimetext": { + "version": "3.0.27", + "resolved": "https://registry.npmjs.org/mimetext/-/mimetext-3.0.27.tgz", + "integrity": "sha512-mUhWAsZD1N/K6dbN4+a5Yq78OPnYQw1ubOSMasBntsLQ2S7KVNlvDEA8dwpr4a7PszWMzeslKahAprtwYMgaBA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@babel/runtime-corejs3": "^7.26.0", + "js-base64": "^3.7.7", + "mime-types": "^2.1.35" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "patreon", + "url": "https://patreon.com/muratgozel" } }, - "node_modules/syncpack/node_modules/chalk-template": { - "version": "1.1.0", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^5.2.0" - }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/chalk-template?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/syncpack/node_modules/globby": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", - "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", - "dev": true, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=18" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/syncpack/node_modules/js-yaml": { - "version": "4.1.0", + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "minipass": "^7.1.2" }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "bin": { - "js-yaml": "bin/js-yaml.js" + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/syncpack/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/syncpack/node_modules/read-yaml-file": { - "version": "2.1.0", - "dev": true, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "license": "MIT", "dependencies": { - "js-yaml": "^4.0.0", - "strip-bom": "^4.0.0" + "whatwg-url": "^5.0.0" }, "engines": { - "node": ">=10.13" + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/syncpack/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" } }, - "node_modules/syncpack/node_modules/strip-bom": { - "version": "4.0.0", + "node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12.19" } }, - "node_modules/table-layout": { - "version": "3.0.2", + "node_modules/nopt": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@75lb/deep-merge": "^1.1.1", - "array-back": "^6.2.2", - "command-line-args": "^5.2.1", - "command-line-usage": "^7.0.0", - "stream-read-all": "^3.0.1", - "typical": "^7.1.1", - "wordwrapjs": "^5.1.0" + "abbrev": "^3.0.0" }, "bin": { - "table-layout": "bin/cli.js" + "nopt": "bin/nopt.js" }, "engines": { - "node": ">=12.17" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/table-layout/node_modules/array-back": { - "version": "6.2.2", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", "engines": { - "node": ">=12.17" + "node": ">=0.10.0" } }, - "node_modules/table-layout/node_modules/typical": { - "version": "7.1.1", + "node_modules/npm-package-arg": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.2.tgz", + "integrity": "sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "hosted-git-info": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^6.0.0" + }, "engines": { - "node": ">=12.17" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", "dev": true, + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tar-fs": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", - "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, - "dependencies": { - "pump": "^3.0.0", - "tar-stream": "^3.1.5" + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=12" }, - "optionalDependencies": { - "bare-fs": "^2.1.1", - "bare-path": "^2.1.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/teeny-request": { - "version": "9.0.0", - "license": "Apache-2.0", + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.9", - "stream-events": "^1.0.5", - "uuid": "^9.0.0" + "ee-first": "1.1.1" }, "engines": { - "node": ">=14" + "node": ">= 0.8" } }, - "node_modules/teeny-request/node_modules/@tootallnate/once": { - "version": "2.0.0", + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "license": "MIT", "engines": { - "node": ">= 10" + "node": ">= 0.8" } }, - "node_modules/teeny-request/node_modules/agent-base": { - "version": "6.0.2", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "4" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">= 6.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/teeny-request/node_modules/http-proxy-agent": { - "version": "5.0.0", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, "license": "MIT", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { - "node": ">= 6" + "node": ">= 0.8.0" } }, - "node_modules/teeny-request/node_modules/https-proxy-agent": { - "version": "5.0.1", + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "dev": true, "license": "MIT", "dependencies": { - "agent-base": "6", - "debug": "4" + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">= 6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/teeny-request/node_modules/uuid": { - "version": "9.0.1", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/temp-dir": { - "version": "3.0.0", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, "engines": { - "node": ">=14.16" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/term-size": { - "version": "2.2.1", + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/terser": { - "version": "5.30.3", - "devOptional": true, - "license": "BSD-2-Clause", + "node_modules/package-config": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/package-config/-/package-config-5.0.0.tgz", + "integrity": "sha512-GYTTew2slBcYdvRHqjhwaaydVMvn/qrGC323+nKclYioNSLTDUM/lGgtGTgyHVtYcozb+XkE8CNhwcraOmZ9Mg==", + "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" + "find-up-simple": "^1.0.0", + "load-json-file": "^7.0.1" }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "devOptional": true, - "license": "MIT" + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" }, - "node_modules/test-exclude": { - "version": "6.0.0", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "license": "ISC", - "peer": true, + "license": "MIT", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "callsites": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", + "node_modules/parent-module/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=6" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, - "license": "ISC", - "peer": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { - "node": "*" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/text-decoder": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.0.tgz", - "integrity": "sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw==", + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "dev": true, + "license": "MIT", "dependencies": { - "b4a": "^1.6.4" + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/text-table": { - "version": "0.2.0", + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, - "license": "MIT" - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } }, - "node_modules/tightrope": { - "version": "0.2.0", - "dev": true, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "license": "MIT", "engines": { - "node": ">=16" + "node": ">= 0.8" } }, - "node_modules/time-zone": { - "version": "1.0.0", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true - }, - "node_modules/tinyexec": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", - "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", - "dev": true - }, - "node_modules/tinypool": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.0.tgz", - "integrity": "sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">=0.10.0" } }, - "node_modules/tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", - "dev": true, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", "engines": { - "node": ">=14.0.0" + "node": ">=8" } }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", - "dev": true, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, "engines": { - "node": ">=14.0.0" + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tldts": { - "version": "6.1.47", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.47.tgz", - "integrity": "sha512-R/K2tZ5MiY+mVrnSkNJkwqYT2vUv1lcT6wJvd2emGaMJ7PHUGRY4e3tUsdFCXgqxi2QgbHjL3yJgXCo40v9Hxw==", + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", "dev": true, - "dependencies": { - "tldts-core": "^6.1.47" + "license": "MIT", + "engines": { + "node": ">=18" }, - "bin": { - "tldts": "bin/cli.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tldts-core": { - "version": "6.1.47", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.47.tgz", - "integrity": "sha512-6SWyFMnlst1fEt7GQVAAu16EGgFK0cLouH/2Mk6Ftlwhv3Ol40L0dlpGMcnnNiiOMyD2EV/aF3S+U2nKvvLvrA==", - "dev": true - }, - "node_modules/tmp": { - "version": "0.0.33", - "dev": true, - "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, + "node_modules/pdfjs-dist": { + "version": "5.4.449", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.4.449.tgz", + "integrity": "sha512-CegnUaT0QwAyQMS+7o2POr4wWUNNe8VaKKlcuoRHeYo98cVnqPpwOXNSx6Trl6szH02JrRcsPgletV6GmF3LtQ==", + "license": "Apache-2.0", "engines": { - "node": ">=0.6.0" + "node": ">=20.16.0 || >=22.3.0" + }, + "optionalDependencies": { + "@napi-rs/canvas": "^0.1.81" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "dev": true, - "license": "BSD-3-Clause", - "peer": true + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "dev": true, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" + "node": ">=12" }, - "engines": { - "node": ">=8.0" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/toidentifier": { - "version": "1.0.1", + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", "license": "MIT", "engines": { - "node": ">=0.6" + "node": ">=16.20.0" } }, - "node_modules/token-stream": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/tough-cookie": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", - "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "node_modules/plur": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", + "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", "dev": true, + "license": "MIT", "dependencies": { - "tldts": "^6.1.32" + "irregular-plurals": "^3.3.0" }, "engines": { - "node": ">=16" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tr46": { - "version": "3.0.0", - "dev": true, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "dependencies": { - "punycode": "^2.1.1" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">=12" + "node": "^10 || ^12 || >=14" } }, - "node_modules/tr46/node_modules/punycode": { - "version": "2.3.1", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "node_modules/ts-api-utils": { - "version": "1.3.0", + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, "engines": { - "node": ">=16" + "node": ">=14" }, - "peerDependencies": { - "typescript": ">=4.2.0" + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/ts-deepmerge": { - "version": "2.0.7", - "dev": true, - "license": "ISC" - }, - "node_modules/ts-expose-internals-conditionally": { - "version": "1.0.0-empty.0", - "dev": true, - "license": "MIT" - }, - "node_modules/ts-json-schema-generator": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ts-json-schema-generator/-/ts-json-schema-generator-2.3.0.tgz", - "integrity": "sha512-t4lBQAwZc0sOJq9LJt3NgbznIcslVnm0JeEMFq8qIRklpMRY8jlYD0YmnRWbqBKANxkby91P1XanSSlSOFpUmg==", + "node_modules/pretty-ms": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", + "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.15", - "commander": "^12.0.0", - "glob": "^10.3.12", - "json5": "^2.2.3", - "normalize-path": "^3.0.0", - "safe-stable-stringify": "^2.4.3", - "tslib": "^2.6.2", - "typescript": "^5.4.5" + "parse-ms": "^4.0.0" }, - "bin": { - "ts-json-schema-generator": "bin/ts-json-schema-generator.js" + "engines": { + "node": ">=18" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/proc-log": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", + "dev": true, + "license": "ISC", "engines": { - "node": ">=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/ts-node": { - "version": "10.9.2", + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "engines": { + "node": ">= 6" } }, - "node_modules/ts-node/node_modules/arg": { - "version": "4.1.3", - "license": "MIT" - }, - "node_modules/ts-toolbelt": { - "version": "9.6.0", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", "dev": true, "license": "MIT", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", + "node_modules/proper-lockfile/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, + "license": "ISC" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "license": "MIT", "dependencies": { - "minimist": "^1.2.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">= 0.10" } }, - "node_modules/tslib": { - "version": "2.6.2", - "license": "0BSD" - }, - "node_modules/tsscmp": { - "version": "1.0.6", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.6.x" + "node": ">=6" } }, - "node_modules/tsx": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz", - "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==", - "dev": true, - "dependencies": { - "esbuild": "~0.23.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "node": ">=6" } }, - "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", - "cpu": [ - "ppc64" - ], + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, - "optional": true, - "os": [ - "aix" + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, "engines": { - "node": ">=18" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", - "cpu": [ - "arm" - ], + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "optional": true, - "os": [ - "android" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { - "node": ">=18" + "node": ">= 0.6" } }, - "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], + "node_modules/raw-body": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", + "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.7.0", + "unpipe": "1.0.0" + }, "engines": { - "node": ">=18" + "node": ">= 0.10" } }, - "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", - "cpu": [ - "x64" - ], + "node_modules/read-yaml-file": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-2.1.0.tgz", + "integrity": "sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "license": "MIT", + "dependencies": { + "js-yaml": "^4.0.0", + "strip-bom": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": ">=10.13" } }, - "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">=18" + "node": ">= 6" } }, - "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", - "cpu": [ - "x64" - ], + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, "engines": { - "node": ">=18" + "node": ">=8.10.0" } }, - "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", - "cpu": [ - "arm64" - ], + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", - "cpu": [ - "x64" - ], + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", - "cpu": [ - "arm64" - ], + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", - "cpu": [ - "ia32" - ], + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", - "cpu": [ - "loong64" - ], + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "devOptional": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", - "cpu": [ - "mips64el" - ], + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", "engines": { - "node": ">=18" + "node": ">= 4" } }, - "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/retry-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", + "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", + "license": "MIT", + "dependencies": { + "@types/request": "^2.48.8", + "extend": "^3.0.2", + "teeny-request": "^9.0.0" + }, "engines": { - "node": ">=18" + "node": ">=14" } }, - "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", - "cpu": [ - "riscv64" - ], + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", "engines": { - "node": ">=18" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", - "cpu": [ - "s390x" - ], + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", - "cpu": [ - "x64" - ], + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", - "cpu": [ - "x64" - ], + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "optional": true, - "os": [ - "netbsd" - ], + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">=18" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", - "cpu": [ - "arm64" - ], + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "optional": true, - "os": [ - "openbsd" - ], + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], + "node_modules/rollup": { + "version": "4.53.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.2.tgz", + "integrity": "sha512-MHngMYwGJVi6Fmnk6ISmnk7JAHRNF0UkuucA0CUW3N3a4KnONPEZz+vUanQP/ZC/iY1Qkf3bwPWzyY84wEks1g==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, "engines": { - "node": ">=18" + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.2", + "@rollup/rollup-android-arm64": "4.53.2", + "@rollup/rollup-darwin-arm64": "4.53.2", + "@rollup/rollup-darwin-x64": "4.53.2", + "@rollup/rollup-freebsd-arm64": "4.53.2", + "@rollup/rollup-freebsd-x64": "4.53.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.2", + "@rollup/rollup-linux-arm-musleabihf": "4.53.2", + "@rollup/rollup-linux-arm64-gnu": "4.53.2", + "@rollup/rollup-linux-arm64-musl": "4.53.2", + "@rollup/rollup-linux-loong64-gnu": "4.53.2", + "@rollup/rollup-linux-ppc64-gnu": "4.53.2", + "@rollup/rollup-linux-riscv64-gnu": "4.53.2", + "@rollup/rollup-linux-riscv64-musl": "4.53.2", + "@rollup/rollup-linux-s390x-gnu": "4.53.2", + "@rollup/rollup-linux-x64-gnu": "4.53.2", + "@rollup/rollup-linux-x64-musl": "4.53.2", + "@rollup/rollup-openharmony-arm64": "4.53.2", + "@rollup/rollup-win32-arm64-msvc": "4.53.2", + "@rollup/rollup-win32-ia32-msvc": "4.53.2", + "@rollup/rollup-win32-x64-gnu": "4.53.2", + "@rollup/rollup-win32-x64-msvc": "4.53.2", + "fsevents": "~2.3.2" } }, - "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, "engines": { - "node": ">=18" + "node": ">= 18" } }, - "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "node_modules/router/node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", - "cpu": [ - "ia32" - ], + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, - "optional": true, - "os": [ - "win32" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } ], - "engines": { - "node": ">=18" + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", - "cpu": [ - "x64" + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, "engines": { - "node": ">=18" + "node": ">=v12.22.7" } }, - "node_modules/tsx/node_modules/esbuild": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", - "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "node_modules/screens": { + "resolved": "experiments/screens", + "link": true + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, - "hasInstallScript": true, + "license": "ISC", "bin": { - "esbuild": "bin/esbuild" + "semver": "bin/semver.js" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.1", - "@esbuild/android-arm": "0.23.1", - "@esbuild/android-arm64": "0.23.1", - "@esbuild/android-x64": "0.23.1", - "@esbuild/darwin-arm64": "0.23.1", - "@esbuild/darwin-x64": "0.23.1", - "@esbuild/freebsd-arm64": "0.23.1", - "@esbuild/freebsd-x64": "0.23.1", - "@esbuild/linux-arm": "0.23.1", - "@esbuild/linux-arm64": "0.23.1", - "@esbuild/linux-ia32": "0.23.1", - "@esbuild/linux-loong64": "0.23.1", - "@esbuild/linux-mips64el": "0.23.1", - "@esbuild/linux-ppc64": "0.23.1", - "@esbuild/linux-riscv64": "0.23.1", - "@esbuild/linux-s390x": "0.23.1", - "@esbuild/linux-x64": "0.23.1", - "@esbuild/netbsd-x64": "0.23.1", - "@esbuild/openbsd-arm64": "0.23.1", - "@esbuild/openbsd-x64": "0.23.1", - "@esbuild/sunos-x64": "0.23.1", - "@esbuild/win32-arm64": "0.23.1", - "@esbuild/win32-ia32": "0.23.1", - "@esbuild/win32-x64": "0.23.1" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, "engines": { - "node": "*" + "node": ">= 0.8.0" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "dev": true, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">= 0.8.0" + "node": ">=4" } }, - "node_modules/type-detect": { - "version": "4.0.8", + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", "dev": true, "license": "MIT", - "peer": true, + "dependencies": { + "type-fest": "^0.13.1" + }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/type-fest": { - "version": "0.20.2", + "node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -23008,40 +7607,75 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/type-is": { - "version": "1.6.18", + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "dev": true, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "dev": true, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" }, "engines": { "node": ">= 0.4" @@ -23050,17 +7684,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "dev": true, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" }, "engines": { "node": ">= 0.4" @@ -23069,17 +7702,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "dev": true, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -23088,1597 +7721,2109 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-query-selector": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", - "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", - "dev": true + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true + "node_modules/signal-polyfill": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/signal-polyfill/-/signal-polyfill-0.2.2.tgz", + "integrity": "sha512-p63Y4Er5/eMQ9RHg0M0Y64NlsQKpiu6MDdhBXpyywRuWiPywhJTpKJ1iB5K2hJEbFZ0BnDS7ZkJ+0AfTuL37Rg==", + "license": "Apache-2.0" }, - "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" + "node_modules/signal-utils": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/signal-utils/-/signal-utils-0.21.1.tgz", + "integrity": "sha512-i9cdLSvVH4j8ql8mz2lyrA93xL499P8wEbIev3ldSriXeUwqh+wM4Q5VPhIZ19gPtIS4BOopJuKB8l1+wH9LCg==", + "license": "MIT", + "peerDependencies": { + "signal-polyfill": "^0.2.0" } }, - "node_modules/typescript-4.8": { - "name": "typescript", - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } + "license": "MIT" }, - "node_modules/typescript-4.9": { - "name": "typescript", - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", "engines": { - "node": ">=4.2.0" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typescript-5.0": { - "name": "typescript", - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" }, "engines": { - "node": ">=12.20" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/typescript-5.1": { - "name": "typescript", - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", "engines": { - "node": ">=14.17" + "node": ">=0.10.0" } }, - "node_modules/typescript-5.2": { - "name": "typescript", - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } + "license": "BSD-3-Clause" }, - "node_modules/typescript-5.3": { - "name": "typescript", - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" }, "engines": { - "node": ">=14.17" + "node": ">=10" } }, - "node_modules/typescript-5.4": { - "name": "typescript", - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", "engines": { - "node": ">=14.17" + "node": ">=8" } }, - "node_modules/typescript-5.5": { - "name": "typescript", - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { - "node": ">=14.17" + "node": ">= 0.8" } }, - "node_modules/typescript-5.6": { - "name": "typescript", - "version": "5.6.0-dev.20240819", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.0-dev.20240819.tgz", - "integrity": "sha512-uNOMaNm8jBELjhuXZG5tSS6Pa6O/Wf89hawKkWaZcZvbkgkY2ykvNTNrkCP7QCQTSS3jwEVvd+pRhxJPxUeG4g==", + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", "engines": { - "node": ">=14.17" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "license": "MIT", + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" } }, - "node_modules/typescript-5.7": { - "name": "typescript", - "version": "5.7.0-dev.20240823", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.0-dev.20240823.tgz", - "integrity": "sha512-RC1ePjOemjV49k7p0C5NwjawdKRFN5Gej5VWOBpgJgzj8VCzldBso00cOIg3VPZOFjSuNEJ5mS7vKoMsn9mmew==", + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=14.17" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typescript-json-schema": { - "version": "0.65.1", - "resolved": "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.65.1.tgz", - "integrity": "sha512-tuGH7ff2jPaUYi6as3lHyHcKpSmXIqN7/mu50x3HlYn0EHzLpmt3nplZ7EuhUkO0eqDRc9GqWNkfjgBPIS9kxg==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.9", - "@types/node": "^18.11.9", - "glob": "^7.1.7", - "path-equal": "^1.2.5", - "safe-stable-stringify": "^2.2.0", - "ts-node": "^10.9.1", - "typescript": "~5.5.0", - "yargs": "^17.1.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "bin": { - "typescript-json-schema": "bin/typescript-json-schema" + "engines": { + "node": ">=8" } }, - "node_modules/typescript-json-schema/node_modules/@types/node": { - "version": "18.19.51", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.51.tgz", - "integrity": "sha512-IIMkWEIVQDlBpi6pPeGqTqOx7KbzGC3EgIyH8NrxplXOwWw0uVl9vthJUMFrxD7kcEfcRp7jIkgpB28M6JnfWA==", - "dependencies": { - "undici-types": "~5.26.4" + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/typescript-json-schema/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/typescript-json-schema/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/typescript-json-schema/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "ansi-regex": "^5.0.1" }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/typescript-json-schema/node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { - "node": ">=14.17" + "node": ">=8" } }, - "node_modules/typical": { + "node_modules/strip-bom": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/ua-parser-js": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.38.tgz", - "integrity": "sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==", + "node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, { "type": "github", - "url": "https://github.com/sponsors/faisalman" + "url": "https://github.com/sponsors/NaturalIntelligence" } ], - "engines": { - "node": "*" - } + "license": "MIT" }, - "node_modules/uc.micro": { - "version": "2.1.0", + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", "license": "MIT" }, - "node_modules/uglify-js": { - "version": "3.17.4", + "node_modules/supertap": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/supertap/-/supertap-3.0.1.tgz", + "integrity": "sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==", "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" + "license": "MIT", + "dependencies": { + "indent-string": "^5.0.0", + "js-yaml": "^3.14.1", + "serialize-error": "^7.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=0.8.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/unbox-primitive": { - "version": "1.0.2", + "node_modules/supertap/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/supertap/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "node_modules/svg-path-properties": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/svg-path-properties/-/svg-path-properties-0.2.2.tgz", + "integrity": "sha512-GmrB+b6woz6CCdQe6w1GHs/1lt25l7SR5hmhF8jRdarpv/OgjLyuQygLu1makJapixeb1aQhP/Oa1iKi93o/aQ==", + "license": "ISC" }, - "node_modules/unicode-emoji-modifier-base": { - "version": "1.0.0", + "node_modules/svgpath": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/svgpath/-/svgpath-2.6.0.tgz", + "integrity": "sha512-OIWR6bKzXvdXYyO4DK/UWa1VA1JeKq8E+0ug2DG98Y/vOmMpfZNj+TIG988HjfYSqtcy/hFOtZq/n/j5GSESNg==", + "license": "MIT", + "funding": { + "url": "https://github.com/fontello/svg2ttf?sponsor=1" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/syncpack": { + "version": "13.0.4", + "resolved": "https://registry.npmjs.org/syncpack/-/syncpack-13.0.4.tgz", + "integrity": "sha512-kJ9VlRxNCsBD5pJAE29oXeBYbPLhEySQmK4HdpsLv81I6fcDDW17xeJqMwiU3H7/woAVsbgq25DJNS8BeiN5+w==", "dev": true, "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "chalk-template": "^1.1.0", + "commander": "^13.1.0", + "cosmiconfig": "^9.0.0", + "effect": "^3.13.7", + "enquirer": "^2.4.1", + "fast-check": "^3.23.2", + "globby": "^14.1.0", + "jsonc-parser": "^3.3.1", + "minimatch": "9.0.5", + "npm-package-arg": "^12.0.2", + "ora": "^8.2.0", + "prompts": "^2.4.2", + "read-yaml-file": "^2.1.0", + "semver": "^7.7.1", + "tightrope": "0.2.0", + "ts-toolbelt": "^9.6.0" + }, + "bin": { + "syncpack": "dist/bin.js", + "syncpack-fix-mismatches": "dist/bin-fix-mismatches/index.js", + "syncpack-format": "dist/bin-format/index.js", + "syncpack-lint": "dist/bin-lint/index.js", + "syncpack-lint-semver-ranges": "dist/bin-lint-semver-ranges/index.js", + "syncpack-list": "dist/bin-list/index.js", + "syncpack-list-mismatches": "dist/bin-list-mismatches/index.js", + "syncpack-prompt": "dist/bin-prompt/index.js", + "syncpack-set-semver-ranges": "dist/bin-set-semver-ranges/index.js", + "syncpack-update": "dist/bin-update/index.js" + }, "engines": { - "node": ">=4" + "node": ">=18.18.0" } }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "node_modules/tar": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", + "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, "engines": { "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/tar-mini": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tar-mini/-/tar-mini-0.2.0.tgz", + "integrity": "sha512-+qfUHz700DWnRutdUsxRRVZ38G1Qr27OetwaMYTdg8hcPxf46U0S1Zf76dQMWRBmusOt2ZCK5kbIaiLkoGO7WQ==", "dev": true, - "engines": { - "node": ">= 4.0.0" - } + "license": "MIT" }, - "node_modules/unpipe": { - "version": "1.0.0", - "license": "MIT", + "node_modules/teeny-request": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", + "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", + "license": "Apache-2.0", + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.9", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=14" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/teeny-request/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", - "peer": true, "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" + "debug": "4" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "engines": { + "node": ">= 6.0.0" } }, - "node_modules/update-check": { - "version": "1.5.4", + "node_modules/teeny-request/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "license": "MIT", "dependencies": { - "registry-auth-token": "3.3.2", - "registry-url": "3.1.0" + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "license": "BSD-2-Clause", + "node_modules/teeny-request/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", "dependencies": { - "punycode": "^2.1.0" + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/uri-js/node_modules/punycode": { - "version": "2.3.1", + "node_modules/teeny-request/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", - "engines": { - "node": ">=6" + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/url-template": { - "version": "3.1.1", - "license": "BSD-3-Clause", + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=14.16" } }, - "node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "license": "MIT" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, "license": "MIT" }, - "node_modules/utils-merge": { - "version": "1.0.1", + "node_modules/tightrope": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tightrope/-/tightrope-0.2.0.tgz", + "integrity": "sha512-Kw36UHxJEELq2VUqdaSGR2/8cAsPgMtvX8uGVU6Jk26O66PhXec0A5ZnRYs47btbtwPDpXXF66+Fo3vimCM9aQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4.0" + "node": ">=16" } }, - "node_modules/uuid": { - "version": "8.3.2", + "node_modules/time-zone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", + "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", + "dev": true, "license": "MIT", - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" + "engines": { + "node": ">=4" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "license": "MIT" - }, - "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "dev": true, - "license": "ISC", + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": ">=10.12.0" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/tldts": { + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz", + "integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==", "dev": true, + "license": "MIT", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "tldts-core": "^7.0.19" + }, + "bin": { + "tldts": "bin/cli.js" } }, - "node_modules/validate-npm-package-name": { - "version": "5.0.0", + "node_modules/tldts-core": { + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.19.tgz", + "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "builtins": "^5.0.0" + "is-number": "^7.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=8.0" } }, - "node_modules/vary": { - "version": "1.1.2", + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "license": "MIT", "engines": { - "node": ">= 0.8" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "node": ">=0.6" } }, - "node_modules/vite": { - "version": "5.4.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", - "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", + "node_modules/topojson-client": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", + "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", + "license": "ISC", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "commander": "2" }, "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "topo2geo": "bin/topo2geo", + "topomerge": "bin/topomerge", + "topoquantize": "bin/topoquantize" } }, - "node_modules/vite-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.1.tgz", - "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", + "node_modules/topojson-client/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/tough-cookie": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", + "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.6", - "pathe": "^1.1.2", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" + "tldts": "^7.0.5" }, "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "node": ">=16" } }, - "node_modules/vite-plugin-full-reload": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.2.0.tgz", - "integrity": "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA==", - "dev": true, - "dependencies": { - "picocolors": "^1.0.0", - "picomatch": "^2.3.1" - } + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" }, - "node_modules/vite-plugin-full-reload/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=18.12" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "node_modules/vite-plugin-watch-and-run": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/vite-plugin-watch-and-run/-/vite-plugin-watch-and-run-1.7.1.tgz", - "integrity": "sha512-knLbovXBUwVrm0q4+LcpIhqTAZRoWVv5m8xRn42dy8hrF3rgJ7ucxm1d99KecED87NZI7v5oH3Pc2sPDcwJKEQ==", + "node_modules/ts-toolbelt": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", + "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==", "dev": true, + "license": "Apache-2.0" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.20.6", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", + "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", + "devOptional": true, "license": "MIT", "dependencies": { - "@kitql/helpers": "0.8.10", - "micromatch": "4.0.8" + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" }, "engines": { - "node": "^16.14 || >=18" + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", "cpu": [ "ppc64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "node_modules/tsx/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", "cpu": [ "arm" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "node_modules/tsx/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", "cpu": [ "arm64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "node_modules/tsx/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", "cpu": [ "x64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", "cpu": [ "arm64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "node_modules/tsx/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", "cpu": [ "x64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", "cpu": [ "arm64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", "cpu": [ "x64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "node_modules/tsx/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", "cpu": [ "arm" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "node_modules/tsx/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", "cpu": [ "arm64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "node_modules/tsx/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", "cpu": [ "ia32" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "node_modules/tsx/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", "cpu": [ "loong64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", "cpu": [ "mips64el" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", "cpu": [ "ppc64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", "cpu": [ "riscv64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "node_modules/tsx/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", "cpu": [ "s390x" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "node_modules/tsx/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", "cpu": [ "x64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", "cpu": [ "x64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ - "netbsd" + "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", "cpu": [ - "x64" + "arm64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ - "openbsd" + "openharmony" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "node_modules/tsx/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", "cpu": [ "x64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "node_modules/tsx/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", "cpu": [ "arm64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "node_modules/tsx/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", "cpu": [ "ia32" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "node_modules/tsx/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", "cpu": [ "x64" ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "node_modules/tsx/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "devOptional": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/vitest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.1.tgz", - "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", - "dev": true, - "dependencies": { - "@vitest/expect": "2.1.1", - "@vitest/mocker": "2.1.1", - "@vitest/pretty-format": "^2.1.1", - "@vitest/runner": "2.1.1", - "@vitest/snapshot": "2.1.1", - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", - "chai": "^5.1.1", - "debug": "^4.3.6", - "magic-string": "^0.30.11", - "pathe": "^1.1.2", - "std-env": "^3.7.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.0", - "tinypool": "^1.0.0", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.1", - "why-is-node-running": "^2.3.0" + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urlpattern-polyfill": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", + "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==", + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.2.tgz", + "integrity": "sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfs": { + "resolved": "experiments/agent", + "link": true + }, + "node_modules/vite": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz", + "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, "bin": { - "vitest": "vitest.mjs" + "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { - "url": "https://opencollective.com/vitest" + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" }, "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.1", - "@vitest/ui": "2.1.1", - "happy-dom": "*", - "jsdom": "*" + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { - "@edge-runtime/vm": { + "@types/node": { "optional": true }, - "@types/node": { + "jiti": { "optional": true }, - "@vitest/browser": { + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { "optional": true }, - "@vitest/ui": { + "terser": { "optional": true }, - "happy-dom": { + "tsx": { "optional": true }, - "jsdom": { + "yaml": { "optional": true } } }, - "node_modules/void-elements": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", - "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node_modules/vite-express": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/vite-express/-/vite-express-0.21.1.tgz", + "integrity": "sha512-/dz1syfdKfWwcNRSl9wxZQmH7dImrvxNR9TptbpYGqrlawWFD+USzbLR1ytWei8XJpDPDRUgOoT8dEIf/vviyQ==", + "license": "MIT", + "dependencies": { + "express-static-gzip": "^2.2.0", + "picocolors": "^1.1.1" } }, - "node_modules/w3c-keyname": { - "version": "2.2.8", - "license": "MIT" - }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", + "node_modules/vite-plugin-compression2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/vite-plugin-compression2/-/vite-plugin-compression2-2.3.1.tgz", + "integrity": "sha512-bnhLTsurtvOiiP6EMISIKVsOMCeTAjE6FJbyqQus3W4mtAxF7pCuC4puUIAiCgNs98tOCpqo6GIXJXTLufzIaw==", "dev": true, "license": "MIT", "dependencies": { - "xml-name-validator": "^5.0.0" - }, + "@rollup/pluginutils": "^5.1.0", + "tar-mini": "^0.2.0" + } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { "node": ">=18" } }, - "node_modules/walker": { - "version": "1.0.8", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "makeerror": "1.0.12" + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "license": "Apache-2.0", - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.8.0" + "node": ">=18" } }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "license": "Apache-2.0", + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.8.0" + "node": ">=18" } }, - "node_modules/well-known-symbols": { - "version": "2.0.0", - "dev": true, - "license": "ISC", + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6" + "node": ">=18" } }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "dev": true, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "iconv-lite": "0.6.3" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { "node": ">=18" } }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "dev": true, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "dev": true, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { "node": ">=18" } }, - "node_modules/whatwg-url": { - "version": "11.0.0", - "dev": true, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], "license": "MIT", - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/which": { - "version": "2.0.2", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">=18" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "dev": true, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], "license": "MIT", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "dev": true, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "license": "MIT", "optional": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "license": "MIT", "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/wide-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "optional": true - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "license": "MIT", "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/wide-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "license": "MIT", "optional": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, + "os": [ + "netbsd" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "license": "MIT", "optional": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "os": [ + "openbsd" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/widest-line": { - "version": "4.0.1", + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "string-width": "^5.0.1" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/wireit": { - "version": "0.14.9", - "resolved": "https://registry.npmjs.org/wireit/-/wireit-0.14.9.tgz", - "integrity": "sha512-hFc96BgyslfO1WGSzQqOVYd5N3TB+4u9w70L9GHR/T7SYjvFmeznkYMsRIjMLhPcVabCEYPW1vV66wmIVDs+dQ==", - "dev": true, - "dependencies": { - "brace-expansion": "^4.0.0", - "chokidar": "^3.5.3", - "fast-glob": "^3.2.11", - "jsonc-parser": "^3.0.0", - "proper-lockfile": "^4.1.2" - }, - "bin": { - "wireit": "bin/wireit.js" - }, + "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/wireit/node_modules/balanced-match": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-3.0.1.tgz", - "integrity": "sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==", - "dev": true, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">= 16" + "node": ">=18" } }, - "node_modules/wireit/node_modules/brace-expansion": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-4.0.0.tgz", - "integrity": "sha512-l/mOwLWs7BQIgOKrL46dIAbyCKvPV7YJPDspkuc88rHsZRlg3hptUGdU7Trv0VFP4d3xnSGBQrKu5ZvGB7UeIw==", - "dev": true, - "dependencies": { - "balanced-match": "^3.0.0" - }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 18" + "node": ">=18" } }, - "node_modules/with": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", - "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.9.6", - "@babel/types": "^7.9.6", - "assert-never": "^1.2.1", - "babel-walk": "3.0.0-canary-5" - }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 10.0.0" + "node": ">=18" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/wordwrapjs": { - "version": "5.1.0", - "dev": true, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12.17" + "node": ">=18" } }, - "node_modules/wrap-ansi": { - "version": "8.1.0", + "node_modules/vite/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=18" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/well-known-symbols": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", + "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, + "license": "ISC", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=6" } }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "license": "ISC" + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "dev": true, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "license": "ISC", "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 8" } }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "4.1.0", + "node_modules/wireit": { + "version": "0.15.0-pre.2", + "resolved": "https://registry.npmjs.org/wireit/-/wireit-0.15.0-pre.2.tgz", + "integrity": "sha512-pXOTR56btrL7STFOPQgtq8MjAFWagSqs188E2FflCgcxk5uc0Xbn8CuLIR9FbqK97U3Jw6AK8zDEu/M/9ENqgA==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "engines": { - "node": ">=10.0.0" + "license": "Apache-2.0", + "workspaces": [ + "vscode-extension", + "website" + ], + "dependencies": { + "brace-expansion": "^4.0.0", + "chokidar": "^3.5.3", + "fast-glob": "^3.2.11", + "jsonc-parser": "^3.0.0", + "proper-lockfile": "^4.1.2" }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "bin": { + "wireit": "bin/wireit.js" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": ">=18.0.0" } }, - "node_modules/xml-name-validator": { - "version": "5.0.0", + "node_modules/wireit/node_modules/balanced-match": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-3.0.1.tgz", + "integrity": "sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": ">=18" + "node": ">= 16" } }, - "node_modules/xmlchars": { - "version": "2.2.0", + "node_modules/wireit/node_modules/brace-expansion": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-4.0.1.tgz", + "integrity": "sha512-YClrbvTCXGe70pU2JiEiPLYXO9gQkyxYeKpJIQHVS/gOs6EWMQP2RYBwjFLNT322Ji8TOC3IMPfsYCedNpzKfA==", "dev": true, - "license": "MIT" - }, - "node_modules/y18n": { - "version": "5.0.8", - "license": "ISC", + "license": "MIT", + "dependencies": { + "balanced-match": "^3.0.0" + }, "engines": { - "node": ">=10" + "node": ">= 18" } }, - "node_modules/yallist": { - "version": "4.0.0", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, - "license": "ISC" - }, - "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", - "bin": { - "yaml": "bin.mjs" - }, + "license": "MIT", "engines": { - "node": ">= 14" + "node": ">=0.10.0" } }, - "node_modules/yargs": { - "version": "17.7.2", + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=12" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "license": "ISC", + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/yargs/node_modules/emoji-regex": { + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/yargs/node_modules/string-width": { + "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -24689,8 +9834,10 @@ "node": ">=8" } }, - "node_modules/yargs/node_modules/strip-ansi": { + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -24699,1286 +9846,350 @@ "node": ">=8" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/ylru": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" }, - "node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "node_modules/write-file-atomic": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-6.0.0.tgz", + "integrity": "sha512-GmqrO8WJ1NuzJ2DrziEI2o57jKAVIQNf8a18W3nCYU3H7PNWqCCVTeH6/NQE93CIllIgQS98rrmVkYgTX9fFJQ==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "packages/agent-kit": { - "name": "@google-labs/agent-kit", - "version": "0.12.0", - "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "^0.10.0" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/gemini-kit": "^0.8.0", - "@google-labs/json-kit": "^0.3.8", - "@google-labs/template-kit": "^0.3.10", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "tsx": "^4.19.1", - "typescript": "^5.6.2" - } - }, - "packages/board-server": { - "name": "@breadboard-ai/board-server", - "version": "0.7.0", - "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/data-store": "^0.2.3", - "@google-cloud/firestore": "^7.10.0", - "@google-cloud/secret-manager": "^5.6.0", - "@google-labs/breadboard": "^0.27.0", - "@lit/context": "^1.1.2", - "better-sqlite3": "^11.3.0", - "lit": "^3.2.0", - "uuid": "^10.0.0", - "vite": "^5.4.8" - }, - "devDependencies": { - "@types/better-sqlite3": "^7.6.11", - "@types/node": "^22.0.0", - "@types/uuid": "^10.0.0", - "esbuild": "^0.24.0", - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" - } - }, - "packages/board-server-management": { - "name": "@breadboard-ai/board-server-management", - "version": "1.17.0", - "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/idb-board-server": "^1.17.0", - "@breadboard-ai/remote-board-server": "^1.17.0", - "@google-labs/breadboard": "^0.27.0", - "idb": "^8.0.0" - }, - "devDependencies": { - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "typescript": "^5.6.2" - } - }, - "packages/board-server-utils": { - "name": "@breadboard-ai/board-server-utils", - "version": "0.1.1", - "license": "Apache-2.0", + "license": "ISC", "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/data-store": "^0.2.3", - "@google-labs/agent-kit": "^0.12.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/breadboard-schema": "^1.8.0" + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" }, - "devDependencies": { - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "typescript": "^5.6.2" + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "packages/board-server/node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "packages/breadboard": { - "name": "@google-labs/breadboard", - "version": "0.27.0", - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard-schema": "^1.8.0", - "json-schema": "^0.4.0" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@definitelytyped/dtslint": "^0.2.23", - "@google-labs/tsconfig": "^0.0.1", - "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@rollup/plugin-terser": "^0.4.4", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "jsonschema": "^1.4.1", - "rollup": "^4.22.4", - "rollup-plugin-dts": "^6.1.1", - "typescript": "^5.6.2" - }, "engines": { - "node": ">=20.14.0" - } - }, - "packages/breadboard-cli": { - "name": "@google-labs/breadboard-cli", - "version": "0.11.2", - "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/import": "0.1.10", - "@breadboard-ai/visual-editor": "^1.19.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/template-kit": "^0.3.10", - "@rollup/plugin-commonjs": "^28.0.0", - "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@rollup/plugin-virtual": "^3.0.2", - "commander": "^12.1.0", - "esbuild": "^0.24.0", - "rollup": "^4.22.4", - "serve": "^14.2.3", - "urlpattern-polyfill": "^10.0.0", - "vite": "^5.4.8", - "yaml": "^2.5.1" - }, - "bin": { - "breadboard": "dist/src/index.js" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/js-yaml": "^4.0.9", - "@types/node": "^22.0.0", - "@types/serve-handler": "^6.1.4", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "openapi-types": "^12.1.3", - "typescript": "^5.6.2" - } - }, - "packages/breadboard-extension": { - "name": "@google-labs/breadboard-extension", - "version": "0.1.14", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.21.0", - "@google-labs/core-kit": "^0.11.0", - "@google-labs/json-kit": "^0.3.1", - "@google-labs/node-nursery-web": "^1.1.4", - "@google-labs/palm-kit": "^0.0.15", - "@google-labs/template-kit": "^0.3.3", - "@types/node": "^20.14.9", - "@types/vscode": "^1.90.0", - "@vscode/debugadapter": "^1.65.0", - "@vscode/vsce": "^2.29.0", - "dotenv": "^16.4.5", - "esbuild": "^0.21.5", - "mermaid": "^10.9.1", - "rimraf": "^5.0.7", - "typescript": "^5.5.3" - }, - "engines": { - "vscode": "^1.85.0" - } - }, - "packages/breadboard-server": { - "name": "@google-labs/breadboard-server", - "version": "0.1.17", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-cloud/firestore": "^7.9.0", - "@google-labs/breadboard": "^0.21.0" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/core-kit": "^0.11.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/express": "^4.17.17", - "@types/node": "^20.14.9", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "ava": "^5.2.0", - "jsonschema": "^1.4.1", - "typescript": "^5.5.3" - } - }, - "packages/breadboard-ui": { - "name": "@google-labs/breadboard-ui", - "version": "0.9.0", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@dagrejs/dagre": "^1.1.3", - "@google-labs/breadboard": "^0.21.0", - "@lit/context": "^1.1.2", - "@lit/task": "^1.0.1", - "ajv": "^8.16.0", - "lit": "^3.1.4", - "markdown-it": "^14.1.0", - "pixi.js": "^8.2.1" - }, - "devDependencies": { - "@google-labs/tsconfig": "^0.0.1", - "@rollup/plugin-node-resolve": "^15.2.3", - "@rollup/plugin-terser": "^0.4.4", - "@types/markdown-it": "^14.1.1", - "@types/node": "^20.14.9", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "rollup": "^4.18.0", - "typescript": "^5.5.2" - } - }, - "packages/breadboard-web": { - "name": "@google-labs/breadboard-web", - "version": "1.10.0", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "0.7.0", - "@breadboard-ai/google-drive-kit": "0.1.3", - "@breadboard-ai/manifest": "^0.2.0", - "@breadboard-ai/python-wasm": "0.1.2", - "@codemirror/autocomplete": "^6.16.3", - "@codemirror/commands": "^6.6.0", - "@codemirror/lang-javascript": "^6.2.2", - "@google-labs/agent-kit": "^0.8.0", - "@google-labs/breadboard": "^0.21.0", - "@google-labs/breadboard-ui": "^0.9.0", - "@google-labs/core-kit": "^0.11.0", - "@google-labs/gemini-kit": "^0.5.1", - "@google-labs/json-kit": "^0.3.2", - "@google-labs/node-nursery-web": "^1.1.4", - "@google-labs/palm-kit": "^0.0.15", - "@google-labs/template-kit": "^0.3.4", - "@lit/context": "^1.1.2", - "codemirror": "^6.0.1", - "idb": "^8.0.0", - "idb-keyval": "^6.2.1", - "lit": "^3.1.4" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^20.14.9", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "ava": "^5.2.0", - "dotenv": "^16.4.5", - "tsx": "^4.15.8", - "typescript": "^5.5.2", - "vite": "^5.3.2", - "vite-plugin-full-reload": "^1.1.0", - "vite-plugin-watch-and-run": "^1.7.0", - "vitest": "^1.6.0" - } - }, - "packages/breadbuddy": { - "name": "@google-labs/breadbuddy", - "version": "0.0.15", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.21.0", - "@lit/task": "^1.0.1", - "jszip": "^3.10.1", - "lit": "^3.1.4", - "nunjucks": "^3.2.4" - }, - "devDependencies": { - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^20.14.9", - "@types/nunjucks": "^3.2.6", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "vite": "^5.3.2", - "vite-plugin-full-reload": "^1.1.0", - "vite-plugin-watch-and-run": "^1.7.0", - "vitest": "^1.6.0", - "wireit": "^0.14.4" - } - }, - "packages/build": { - "name": "@breadboard-ai/build", - "version": "0.10.0", - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.27.0", - "@types/json-schema": "^7.0.15" - }, - "devDependencies": { - "@types/node": "^22.0.0", - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" - } - }, - "packages/build-code": { - "name": "@breadboard-ai/build-code", - "version": "0.1.0", - "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@google-labs/core-kit": "^0.15.0", - "@types/node": "^22.0.0", - "esbuild": "^0.24.0", - "json-schema": "^0.4.0", - "json-schema-ref-parser": "^9.0.9", - "prettier": "^3.3.2", - "typescript-json-schema": "^0.65.1" - }, - "bin": { - "build-code": "bin/build-code" - }, - "devDependencies": { - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" - } - }, - "packages/build-legacy": { - "name": "@breadboard-ai/build-legacy", - "version": "0.1.1", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.25.0", - "@google-labs/core-kit": "^0.14.0" - }, - "devDependencies": { - "@types/node": "^22.0.0", - "eslint": "^8.57.0", - "typescript": "^5.5.4", - "wireit": "^0.14.8" - } - }, - "packages/cloud-function": { - "name": "@google-labs/cloud-function", - "version": "0.0.15", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.21.0", - "@google-labs/breadboard-server": "^0.1.17", - "@google-labs/template-kit": "^0.3.3", - "dotenv": "^16.4.5" + "node": ">=10.0.0" }, - "devDependencies": { - "@google-cloud/functions-framework": "^3.4.0", - "ava": "^5.2.0" - } - }, - "packages/coffee-bot-board": { - "name": "@google-labs/coffee-bot-board", - "version": "0.0.15", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@clack/prompts": "^0.7.0", - "@google-labs/breadboard": "^0.20.0", - "@google-labs/core-kit": "^0.9.0", - "@google-labs/json-kit": "^0.3.0", - "@google-labs/node-nursery": "^0.0.15", - "@google-labs/palm-kit": "^0.0.14", - "@google-labs/template-kit": "^0.3.2", - "dotenv": "^16.4.5" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^20.14.5", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", - "ava": "^5.2.0", - "typedoc": "^0.25.12", - "typescript": "^5.4.5" - } - }, - "packages/connection-server": { - "name": "@breadboard-ai/connection-server", - "version": "0.3.2", - "license": "Apache-2.0", - "devDependencies": { - "@types/node": "^22.0.0", - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "packages/core-kit": { - "name": "@google-labs/core-kit", - "version": "0.15.0", + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@google-labs/breadboard": "^0.27.0" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/template-kit": "^0.3.10", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "typescript": "^5.6.2" + "engines": { + "node": ">=18" } }, - "packages/create-breadboard": { - "name": "@google-labs/create-breadboard", - "version": "1.0.13", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.21.0", - "@google-labs/breadboard-hello-world": "^1.2.15", - "chalk": "^5.3.0" - }, - "bin": { - "create-breadboard": "dist/src/index.js" - }, - "devDependencies": { - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^20.14.9", - "@types/semver": "^7.5.8", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "typescript": "^5.5.3" - } - }, - "packages/create-breadboard-kit": { - "name": "@google-labs/create-breadboard-kit", - "version": "0.0.14", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.21.0", - "base-create": "^3.0.8" - }, - "bin": { - "create-breadboard-kit": "dist/src/index.js" - }, - "devDependencies": { - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^20.14.9", - "@types/semver": "^7.5.8", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "typescript": "^5.5.3" - } + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" }, - "packages/data-store": { - "name": "@breadboard-ai/data-store", - "version": "0.2.3", - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.27.0", - "idb": "^8.0.0" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@esm-bundle/chai": "^4.3.4-fix.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/mocha": "^10.0.8", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "@web/dev-server-esbuild": "^1.0.2", - "@web/test-runner": "^0.19.0", - "ava": "^5.2.0", - "esbuild": "^0.24.0", - "typescript": "^5.6.2" - }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", "engines": { - "node": ">=20.14.0" + "node": ">=10" } }, - "packages/discovery-types": { - "name": "@google-labs/discovery-types", - "version": "0.0.1", - "license": "Apache-2.0", - "dependencies": { - "dotenv": "^16.4.5", - "prettier": "^3.3.2" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@types/prettier": "^3.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "typescript": "^5.6.2" + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, - "packages/example-boards": { - "name": "@breadboard-ai/example-boards", - "version": "0.3.2", - "license": "Apache-2.0", + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/google-drive-kit": "0.2.4", - "@breadboard-ai/manifest": "^0.4.4", - "@breadboard-ai/python-wasm": "0.1.6", - "@google-labs/agent-kit": "^0.12.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/gemini-kit": "^0.8.0", - "@google-labs/json-kit": "^0.3.8", - "@google-labs/node-nursery-web": "^1.3.2", - "@google-labs/palm-kit": "^0.1.4", - "@google-labs/template-kit": "^0.3.10" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, - "devDependencies": { - "@google-labs/tsconfig": "^0.0.1", - "tsx": "^4.19.1", - "typescript": "^5.6.2" + "engines": { + "node": ">=12" } }, - "packages/gemini-kit": { - "name": "@google-labs/gemini-kit", - "version": "0.8.0", - "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/template-kit": "^0.3.10" - }, - "devDependencies": { - "@google-labs/breadboard-cli": "^0.11.2", - "@google-labs/tsconfig": "^0.0.1", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "typescript": "^5.6.2" + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" } }, - "packages/google-drive-kit": { - "name": "@breadboard-ai/google-drive-kit", - "version": "0.2.4", - "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/template-kit": "^0.3.10" - }, - "devDependencies": { - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, - "packages/graph-integrity": { - "name": "@google-labs/graph-integrity", - "version": "0.0.14", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.20.0" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^20.14.8", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "ava": "^5.2.0", - "typedoc": "^0.25.12", - "typescript": "^5.4.5" - } - }, - "packages/graph-playground": { - "name": "@google-labs/graph-playground", - "version": "0.0.16", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@clack/prompts": "^0.7.0", - "@google-labs/breadboard": "^0.20.0", - "@google-labs/core-kit": "^0.9.0", - "@google-labs/graph-integrity": "^0.0.14", - "@google-labs/json-kit": "^0.3.0", - "@google-labs/node-nursery": "^0.0.15", - "@google-labs/palm-kit": "^0.0.14", - "@google-labs/pinecone-kit": "^0.1.12", - "@google-labs/template-kit": "^0.3.2", - "dotenv": "^16.4.5" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^20.14.8", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", - "ava": "^5.2.0", - "typedoc": "^0.25.12", - "typescript": "^5.4.5" - } - }, - "packages/graph-runner": { - "name": "@google-labs/graph-runner", - "version": "0.2.0", - "extraneous": true, - "license": "Apache-2.0", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^20.14.5", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", - "ava": "^5.2.0", - "jsonschema": "^1.4.1", - "typedoc": "^0.25.12", - "typescript": "^5.4.5" - } - }, - "packages/hello-world": { - "name": "@google-labs/breadboard-hello-world", - "version": "1.2.20", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-labs/agent-kit": "^0.11.0", - "@google-labs/breadboard": "^0.26.0", - "@google-labs/breadboard-cli": "^0.11.1", - "@google-labs/core-kit": "^0.14.1", - "@google-labs/gemini-kit": "^0.7.0", - "@google-labs/json-kit": "^0.3.7", - "@google-labs/palm-kit": "^0.1.3", - "@google-labs/template-kit": "^0.3.9" - }, - "devDependencies": { - "tsx": "^4.19.1", - "typescript": "^5.5.4" + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, - "packages/idb-board-server": { - "name": "@breadboard-ai/idb-board-server", - "version": "1.17.0", - "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/data-store": "^0.2.3", - "@google-labs/agent-kit": "^0.12.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/breadboard-schema": "^1.8.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/gemini-kit": "^0.8.0", - "@google-labs/json-kit": "^0.3.8", - "@google-labs/node-nursery-web": "^1.3.2", - "@google-labs/palm-kit": "^0.1.4", - "@google-labs/template-kit": "^0.3.10", - "idb": "^8.0.0", - "idb-keyval": "^6.2.1" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@google-labs/tsconfig": "^0.0.1", - "@types/markdown-it": "^14.1.2", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "dotenv": "^16.4.5", - "tsx": "^4.19.1", - "typescript": "^5.6.2", - "vite": "^5.4.8", - "vite-plugin-full-reload": "^1.2.0", - "vite-plugin-watch-and-run": "^1.7.0", - "vitest": "^2.1.1" - } - }, - "packages/import": { - "name": "@breadboard-ai/import", - "version": "0.1.10", - "license": "Apache-2.0", + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", "dependencies": { - "@google-labs/breadboard": "^0.27.0", - "openapi-types": "^12.1.3", - "yaml": "^2.5.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "typescript": "^5.6.2" + "engines": { + "node": ">=8" } }, - "packages/json-kit": { - "name": "@google-labs/json-kit", - "version": "0.3.8", - "license": "Apache-2.0", + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@google-labs/breadboard": "^0.27.0", - "@rgrove/parse-xml": "^4.1.0", - "@types/json-schema": "^7.0.15", - "ajv": "^8.17.1", - "jsonata": "^2.0.5", - "jsonschema": "^1.4.1" + "ansi-regex": "^5.0.1" }, - "devDependencies": { - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "c8": "^10.1.2", - "ts-node": "^10.9.2", - "typescript": "^5.6.2" + "engines": { + "node": ">=8" } }, - "packages/llm-starter": { - "name": "@google-labs/llm-starter", - "version": "0.3.15", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.20.0", - "url-template": "^3.1.0" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^20.14.5", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", - "ava": "^5.2.0", - "typedoc": "^0.25.12", - "typedoc-plugin-markdown": "^4.0.3", - "typescript": "^5.4.5" - } - }, - "packages/manifest": { - "name": "@breadboard-ai/manifest", - "version": "0.4.4", - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.27.0", - "@google-labs/breadboard-schema": "^1.8.0" + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" }, - "devDependencies": { - "@types/node": "^22.0.0", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "ajv-keywords": "^5.1.0", - "c8": "^10.1.2", - "ts-json-schema-generator": "^2.3.0", - "tsx": "^4.19.1", - "typescript": "^5.6.2" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/node-nursery": { - "name": "@google-labs/node-nursery", - "version": "0.0.15", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.20.0", - "@google-labs/chunker": "^0.0.1", - "@google-labs/core-kit": "^0.9.0", - "@google-labs/palm-lite": "^0.0.3", - "@google-labs/template-kit": "^0.3.2", - "json-stable-stringify": "^1.0.2", - "jsonschema": "^1.4.1", - "ml-distance": "^4.0.1", - "sqlite": "^5.0.1", - "sqlite3": "^5.1.6" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/json-stable-stringify": "^1.0.34", - "@types/node": "^20.14.8", - "@types/sqlite3": "^3.1.8", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "ava": "^5.2.0", - "typedoc": "^0.25.12", - "typescript": "^5.4.5" - } - }, - "packages/node-nursery-web": { - "name": "@google-labs/node-nursery-web", - "version": "1.3.2", - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.27.0" + "node_modules/yoctocolors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=18" }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/template-kit": "^0.3.10", - "@google-labs/tsconfig": "^0.0.1", - "@types/gapi": "^0.0.47", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "npm": "^10.8.3", - "typescript": "^5.6.2" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/node-proxy-server": { - "name": "@google-labs/node-proxy-server", - "version": "0.0.2", - "license": "Apache-2.0", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "typescript": "^5.6.2" + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" } }, - "packages/node-proxy-server/functions": { - "dependencies": { - "firebase-admin": "^12.5.0", - "firebase-functions": "^6.0.1" - }, - "devDependencies": { - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/palm-kit": "^0.1.4", - "@google-labs/template-kit": "^0.3.10", - "@rollup/plugin-commonjs": "^28.0.0", - "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@rollup/plugin-terser": "^0.4.4", - "firebase-functions-test": "^3.3.0", - "rollup": "^4.22.4", - "typescript": "^5.6.2" - } - }, - "packages/palm-kit": { - "name": "@google-labs/palm-kit", - "version": "0.1.4", - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.27.0", - "@google-labs/palm-lite": "^0.0.3" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "typescript": "^5.6.2" + "node_modules/zod-to-json-schema": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", + "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.25 || ^4" } }, - "packages/pinecone-kit": { - "name": "@google-labs/pinecone-kit", - "version": "0.1.12", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-labs/breadboard": "^0.20.0", - "@google-labs/core-kit": "^0.9.0" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/template-kit": "^0.3.2", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^20.14.8", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "ava": "^5.2.0", - "typescript": "^5.4.5" - } - }, - "packages/project-store": { - "name": "@breadboard-ai/project-store", - "version": "1.16.1", - "extraneous": true, + "packages/types": { + "name": "@breadboard-ai/types", + "version": "0.9.0", "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "^0.9.1", - "@breadboard-ai/data-store": "^0.2.2", - "@google-labs/breadboard": "^0.26.0", - "@google-labs/breadboard-schema": "^1.7.0", - "idb": "^8.0.0", - "idb-keyval": "^6.2.1" - }, "devDependencies": { - "@ava/typescript": "^4.0.0", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@google-labs/tsconfig": "^0.0.1", - "@types/markdown-it": "^14.1.2", + "@google-labs/tsconfig": "^0.0.2", "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "dotenv": "^16.4.5", - "tsx": "^4.19.1", - "typescript": "^5.5.4", - "vite": "^5.4.6", - "vite-plugin-full-reload": "^1.2.0", - "vite-plugin-watch-and-run": "^1.7.0", - "vitest": "^2.1.1" - } - }, - "packages/python-wasm": { - "name": "@breadboard-ai/python-wasm", - "version": "0.1.6", - "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "pyodide": "^0.26.2" - }, - "devDependencies": { - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" + "typescript": "^5.8.3", + "wireit": "^0.15.0-pre.2" } }, - "packages/remote-board-server": { - "name": "@breadboard-ai/remote-board-server", - "version": "1.17.0", + "packages/unified-server": { + "name": "@breadboard-ai/unified-server", + "version": "0.4.0", "license": "Apache-2.0", "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/data-store": "^0.2.3", - "@google-labs/agent-kit": "^0.12.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/breadboard-schema": "^1.8.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/gemini-kit": "^0.8.0", - "@google-labs/json-kit": "^0.3.8", - "@google-labs/node-nursery-web": "^1.3.2", - "@google-labs/palm-kit": "^0.1.4", - "@google-labs/template-kit": "^0.3.10" + "@breadboard-ai/types": "0.9.0", + "@breadboard-ai/utils": "^0.1.0", + "@breadboard-ai/visual-editor": "1.30.0", + "@google-cloud/storage": "^7.15.2", + "compression": "^1.8.1", + "cookie-parser": "^1.4.7", + "cors": "^2.8.5", + "express": "^4.21.2", + "google-auth-library": "^10.1.0", + "jwt-decode": "^4.0.0", + "vite": "^7.2.6", + "vite-express": "^0.21.1" }, "devDependencies": { - "@ava/typescript": "^4.0.0", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@google-labs/tsconfig": "^0.0.1", - "@types/markdown-it": "^14.1.2", + "@google-labs/tsconfig": "^0.0.2", + "@types/compression": "^1.8.1", + "@types/cookie-parser": "^1.4.10", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.1", + "@types/gtag.js": "^0.0.20", + "@types/jwt-decode": "^2.2.1", "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "dotenv": "^16.4.5", - "tsx": "^4.19.1", - "typescript": "^5.6.2", - "vite": "^5.4.8", - "vite-plugin-full-reload": "^1.2.0", - "vite-plugin-watch-and-run": "^1.7.0", - "vitest": "^2.1.1" - } - }, - "packages/schema": { - "name": "@google-labs/breadboard-schema", - "version": "1.8.0", - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "devDependencies": { - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "ts-json-schema-generator": "^2.3.0" + "@typescript-eslint/eslint-plugin": "^8.43.0", + "@typescript-eslint/parser": "^8.34.1", + "dotenv": "^17.2.3", + "typescript": "^5.8.3", + "vite-plugin-compression2": "^2.2.0", + "wireit": "^0.15.0-pre.2" } }, - "packages/shared-ui": { - "name": "@breadboard-ai/shared-ui", - "version": "1.17.0", - "license": "Apache-2.0", - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/data-store": "^0.2.3", - "@codemirror/autocomplete": "^6.18.1", - "@codemirror/commands": "^6.6.2", - "@codemirror/lang-javascript": "^6.2.2", - "@dagrejs/dagre": "^1.1.4", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/breadboard-schema": "^1.8.0", - "@lit/context": "^1.1.2", - "@lit/task": "^1.0.1", - "@types/gapi": "^0.0.47", - "@types/gapi.drive": "^0.0.9", - "@types/google.picker": "^0.0.42", - "ajv": "^8.17.1", - "codemirror": "^6.0.1", - "idb": "^8.0.0", - "idb-keyval": "^6.2.1", - "lit": "^3.2.0", - "markdown-it": "^14.1.0", - "pixi.js": "^8.4.1" - }, - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@google-labs/tsconfig": "^0.0.1", - "@types/markdown-it": "^14.1.2", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "dotenv": "^16.4.5", - "tsx": "^4.19.1", - "typescript": "^5.6.2", - "vite": "^5.4.8", - "vite-plugin-full-reload": "^1.2.0", - "vite-plugin-watch-and-run": "^1.7.0", - "vitest": "^2.1.1" - } - }, - "packages/team-kit": { - "name": "@google-labs/team-kit", + "packages/utils": { + "name": "@breadboard-ai/utils", "version": "0.1.0", - "extraneous": true, - "license": "Apache-2.0", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/agent-kit": "^0.7.0", - "@google-labs/breadboard": "^0.20.0", - "@google-labs/core-kit": "^0.9.0", - "@google-labs/gemini-kit": "^0.4.0", - "@google-labs/json-kit": "^0.3.0", - "@google-labs/template-kit": "^0.3.2", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^20.14.5", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", - "ava": "^5.2.0", - "tsx": "^4.15.6", - "typescript": "^5.4.5" - } - }, - "packages/template-kit": { - "name": "@google-labs/template-kit", - "version": "0.3.10", "license": "Apache-2.0", "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@google-labs/breadboard": "^0.27.0", - "url-template": "^3.1.0" + "@breadboard-ai/types": "0.9.0", + "@types/gapi.client.drive-v3": "^0.0.5" }, "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", + "@google-labs/tsconfig": "^0.0.2", "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "typescript": "^5.6.2" - } - }, - "packages/v-deprecated-breadboard-ui": { - "name": "@google-labs/breadboard-ui", - "version": "0.9.0", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@dagrejs/dagre": "^1.1.3", - "@google-labs/breadboard": "^0.21.0", - "@lit/context": "^1.1.2", - "@lit/task": "^1.0.1", - "ajv": "^8.16.0", - "lit": "^3.1.4", - "markdown-it": "^14.1.0", - "pixi.js": "^8.2.1" - }, - "devDependencies": { - "@google-labs/tsconfig": "^0.0.1", - "@rollup/plugin-node-resolve": "^15.2.3", - "@rollup/plugin-terser": "^0.4.4", - "@types/markdown-it": "^14.1.1", - "@types/node": "^20.14.9", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "rollup": "^4.18.0", - "typescript": "^5.5.2" + "@typescript-eslint/eslint-plugin": "^8.43.0", + "@typescript-eslint/parser": "^8.34.1", + "ava": "6.4.1", + "typescript": "^5.8.3" } }, "packages/visual-editor": { "name": "@breadboard-ai/visual-editor", - "version": "1.19.0", + "version": "1.30.0", "license": "Apache-2.0", "dependencies": { - "@breadboard-ai/board-server-management": "^1.17.0", - "@breadboard-ai/board-server-utils": "^0.1.1", - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/data-store": "^0.2.3", - "@breadboard-ai/example-boards": "0.3.2", - "@breadboard-ai/google-drive-kit": "0.2.4", - "@breadboard-ai/idb-board-server": "^1.17.0", - "@breadboard-ai/manifest": "^0.4.4", - "@breadboard-ai/python-wasm": "0.1.6", - "@breadboard-ai/shared-ui": "^1.17.0", - "@codemirror/autocomplete": "^6.18.1", - "@codemirror/commands": "^6.6.2", - "@codemirror/lang-javascript": "^6.2.2", - "@dagrejs/dagre": "^1.1.4", - "@google-labs/agent-kit": "^0.12.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/gemini-kit": "^0.8.0", - "@google-labs/json-kit": "^0.3.8", - "@google-labs/node-nursery-web": "^1.3.2", - "@google-labs/palm-kit": "^0.1.4", - "@google-labs/template-kit": "^0.3.10", - "@lit/context": "^1.1.2", - "@lit/task": "^1.0.1", + "@breadboard-ai/types": "0.9.0", + "@breadboard-ai/utils": "^0.1.0", + "@lit-labs/signals": "^0.1.3", + "@lit/context": "^1.1.6", + "@lit/task": "^1.0.2", + "@material/material-color-utilities": "^0.3.0", + "@material/web": "^2.3.0", + "@modelcontextprotocol/sdk": "^1.17.1", "@types/gapi": "^0.0.47", - "@types/gapi.drive": "^0.0.9", - "@types/google.picker": "^0.0.42", + "@types/gapi.client.calendar-v3": "^0.0.4", + "@types/gapi.client.gmail-v1": "^0.0.4", + "@types/google.picker": "^0.0.51", + "@types/trusted-types": "^2.0.7", "ajv": "^8.17.1", - "codemirror": "^6.0.1", - "idb": "^8.0.0", - "idb-keyval": "^6.2.1", - "lit": "^3.2.0", + "comlink": "^4.4.2", + "flubber": "^0.4.2", + "idb": "^8.0.3", + "lit": "^3.3.1", + "littlezipper": "^0.1.5", "markdown-it": "^14.1.0", - "pixi.js": "^8.4.1" + "marked": "^16.3.0", + "mimetext": "^3.0.27", + "pdfjs-dist": "^5.4.449", + "signal-polyfill": "^0.2.2", + "signal-utils": "^0.21.1", + "urlpattern-polyfill": "^10.1.0", + "zod": "^3.24.1", + "zod-to-json-schema": "^3.24.6" }, "devDependencies": { - "@ava/typescript": "^4.0.0", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@google-labs/tsconfig": "^0.0.1", + "@cfworker/json-schema": "^4.1.1", + "@google-labs/tsconfig": "^0.0.2", + "@types/flubber": "^0.4.0", + "@types/gapi": "^0.0.47", + "@types/gapi.client.drive-v3": "^0.0.5", + "@types/google.picker": "^0.0.51", + "@types/gtag.js": "^0.0.20", + "@types/har-format": "^1.2.16", + "@types/jsdom": "^27.0.0", "@types/markdown-it": "^14.1.2", "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "dotenv": "^16.4.5", - "tsx": "^4.19.1", - "typescript": "^5.6.2", - "vite": "^5.4.8", - "vite-plugin-full-reload": "^1.2.0", - "vite-plugin-watch-and-run": "^1.7.0", - "vitest": "^2.1.1" - } - }, - "packages/website": { - "name": "@google-labs/breadboard-website", - "version": "2.6.2", - "license": "Apache-2.0", - "dependencies": { - "@11ty/eleventy-plugin-vite": "^4.0.0", - "@breadboard-ai/shared-ui": "^1.17.0", - "@google-labs/agent-kit": "^0.12.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/gemini-kit": "^0.8.0", - "@google-labs/json-kit": "^0.3.8", - "@google-labs/palm-kit": "^0.1.4", - "@google-labs/template-kit": "^0.3.10", - "eleventy-plugin-youtube-embed": "^1.11.0", - "esbuild": "^0.24.0", - "typescript": "^5.6.2" - }, - "devDependencies": { - "@11ty/eleventy": "^2.0.1", - "@11ty/eleventy-plugin-rss": "^1.2.0", - "@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@koa/cors": "^5.0.0", - "@web/dev-server": "^0.4.6", - "@web/dev-server-esbuild": "^1.0.2", - "jsdom": "^25.0.1", - "lit": "^3.2.0", - "markdown-it-github-alerts": "^0.3.0", - "markdown-it-github-headings": "^2.0.1", - "rollup-plugin-import-assert": "^3.0.1", - "wireit": "^0.14.9" - } - }, - "packages/website/node_modules/rollup": { - "version": "3.29.5", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", - "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "dotenv": "^17.2.3", + "jsdom": "^27.3.0", + "tsx": "^4.20.6", + "typescript": "^5.8.3", + "vite": "^7.2.6" } }, - "packages/website/node_modules/rollup-plugin-import-assert": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-import-assert/-/rollup-plugin-import-assert-3.0.1.tgz", - "integrity": "sha512-7WynDI8B3F/ahhOEus1sDjKCPN3sV5ciV4t717kYlJOst59wJ76e3ig05mQJZZhc8AWpo4V0QMT7mrJpWShh0A==", - "dev": true, + "packages/visual-editor/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", "dependencies": { - "string-to-template-literal": "^2.0.0" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, - "peerDependencies": { - "acorn-import-assertions": "^1.8.0", - "rollup": "^3.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } + }, + "packages/visual-editor/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" } } } diff --git a/package.json b/package.json index 77fb91a3654..24d6dbb9344 100644 --- a/package.json +++ b/package.json @@ -6,14 +6,13 @@ "type": "module", "scripts": { "clean": "git clean -Xdf -e !.vscode/settings.json", - "update": "rimraf package-lock.json && npm i", + "update": "rm package-lock.json && npm i", "test": "wireit", "build": "wireit", "lint": "wireit", - "ci": "npm ci", - "s": "npm run dev -w packages/board-server --watch", - "d": "(cd packages/website && npm run dev) # Starts the docs website", - "w": "(cd packages/visual-editor && npm run dev) # Starts the breadboard web UI", + "dev": "npm run dev -w packages/unified-server --watch", + "dev:next": "npm run dev:next:nowatch --watch", + "dev:next:nowatch": "wireit", "check:format": "prettier --check --config .prettierrc packages/**/*.ts", "ci:local": "wireit", "syncpack:check": "wireit", @@ -26,75 +25,21 @@ "wireit": { "build": { "dependencies": [ - "./packages/agent-kit:build", - "./packages/breadboard:build", - "./packages/breadboard-cli:build", - "./packages/shared-ui:build", - "./packages/visual-editor:build", - "./packages/build:build", - "./packages/build-code:build", - "./packages/connection-server:build", - "./packages/core-kit:build", - "./packages/data-store:build", - "./packages/discovery-types:build", - "./packages/example-boards:build", - "./packages/gemini-kit:build", - "./packages/google-drive-kit:build", - "./packages/idb-board-server:build", - "./packages/import:build", - "./packages/json-kit:build", - "./packages/template-kit:build", - "./packages/node-nursery-web:build", - "./packages/palm-kit:build", - "./packages/python-wasm:build", - "./packages/website:build", - "./packages/schema:build", - "./packages/board-server:build", - "./packages/manifest:build" + "#", + "!./experiments/logic#" ] }, "test": { "dependencies": [ - "./packages/agent-kit:test", - "./packages/board-server:test", - "./packages/breadboard:test", - "./packages/breadboard-cli:test", - "./packages/build:test", - "./packages/build-code:test", - "./packages/connection-server:test", - "./packages/core-kit:test", - "./packages/data-store:test", - "./packages/discovery-types:test", - "./packages/google-drive-kit:test", - "./packages/import:test", - "./packages/json-kit:test", - "./packages/template-kit:test", - "./packages/node-nursery-web:test", - "./packages/palm-kit:test", - "./packages/python-wasm:test", - "./packages/schema:test", - "./packages/manifest:test" + "#", + "!./packages/ui-tests#", + "!./experiments/screens#" ] }, "lint": { "dependencies": [ - "./packages/breadboard:lint", - "./packages/breadboard-cli:lint", - "./packages/build:lint", - "./packages/build-code:lint", - "./packages/connection-server:lint", - "./packages/core-kit:lint", - "./packages/data-store:lint", - "./packages/discovery-types:lint", - "./packages/example-boards:lint", - "./packages/gemini-kit:lint", - "./packages/google-drive-kit:lint", - "./packages/import:lint", - "./packages/json-kit:lint", - "./packages/template-kit:lint", - "./packages/node-nursery-web:lint", - "./packages/palm-kit:lint", - "./packages/python-wasm:lint" + "#", + "!./packages/jsandbox#" ] }, "ci:local": { @@ -111,6 +56,11 @@ "test" ] }, + "dev:next:nowatch": { + "dependencies": [ + "./packages/unified-server:serve" + ] + }, "syncpack:files": { "files": [ "syncpack.config.ts", @@ -149,37 +99,22 @@ "author": "Google Labs Team", "license": "Apache-2.0", "devDependencies": { - "@changesets/cli": "^2.27.8", - "@rollup/plugin-node-resolve": "^15.3.0", - "@rollup/plugin-terser": "^0.4.4", "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", + "@typescript-eslint/eslint-plugin": "^8.43.0", + "@typescript-eslint/parser": "^8.34.1", + "ava": "6.4.1", "eslint": "^8.57.1", - "eslint-plugin-expect-type": "^0.4.3", - "npm-ci": "^0.0.2", - "rimraf": "^6.0.1", - "rollup": "^4.22.4", - "rollup-plugin-dts": "^6.1.1", - "syncpack": "^13.0.0", - "typescript": "^5.6.2", - "wireit": "^0.14.9" + "eslint-plugin-expect-type": "^0.6.2", + "prettier": "^3.6.2", + "syncpack": "^13.0.3", + "typescript": "^5.8.3", + "wireit": "^0.15.0-pre.2" }, "workspaces": [ "./core/*", "./packages/*", - "./packages/node-proxy-server/functions" + "./experiments/*" ], - "optionalDependencies": { - "@rollup/rollup-darwin-arm64": "^4.22.2", - "@rollup/rollup-linux-x64-gnu": "^4.21.2" - }, - "dependencies": { - "json-schema": "^0.4.0", - "litegraph.js": "^0.7.18", - "prettier": "^3.3.2" - }, "repository": { "type": "git", "url": "https://github.com/breadboard-ai/breadboard.git" diff --git a/packages/agent-kit/.eslintrc b/packages/agent-kit/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/agent-kit/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/agent-kit/.gitignore b/packages/agent-kit/.gitignore deleted file mode 100644 index f96c99f8110..00000000000 --- a/packages/agent-kit/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -graphs -src/generated \ No newline at end of file diff --git a/packages/agent-kit/CHANGELOG.md b/packages/agent-kit/CHANGELOG.md deleted file mode 100644 index 16290d44637..00000000000 --- a/packages/agent-kit/CHANGELOG.md +++ /dev/null @@ -1,239 +0,0 @@ -# @google-labs/agent-kit - -## 0.12.0 - -### Minor Changes - -- f61ccf3: Introduce URL-based component types. -- f0b5ccc: Delete tool-worker -- 8540b93: Convert Content to Build API and merge Specialist 2 to Specialist. -- 4c03455: Introduce Specialist 2 and make Content component support LLM Content. -- 84ca649: Introduce the "Content" component. -- 94759f7: Teach Specialist about routing. - -### Patch Changes - -- f94f498: Convert structured worker to build API -- 4e0a4f6: Convert looper to build API -- 58d2e8c: The joiner board has been converted to the new Build API. Should have no functional effect. -- 679719b: Convert specialist to build api -- 9b62fc2: Use new build API kit function -- e63b5dd: Polish Specialist and Content. -- 74d50d4: Convert repeater to Build API (should be a no-op). -- 9ce8ad3: Fix schemas of persona and task -- 7fdf9c2: Add "gemini-1.5-pro-exp-0827" to the choices in Gemini-calling components. -- e38bf19: Set titles for done and loop outputs of looper -- 100fc95: Various fixes and polish. -- e026112: Remind Specialist that it doesn't accept dynamic wires. -- 281ab28: Convert human to build API -- 5fc6e8b: Convert worker board to build API -- Updated dependencies [49e2740] -- Updated dependencies [54c8197] -- Updated dependencies [2f1b85c] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [2fa05f0] -- Updated dependencies [f71bcfb] -- Updated dependencies [3188607] -- Updated dependencies [8540b93] -- Updated dependencies [8330f0c] -- Updated dependencies [1423647] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [91fe8bb] -- Updated dependencies [100fc95] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [5834c81] -- Updated dependencies [0ef793f] - - @breadboard-ai/build@0.10.0 - -## 0.11.0 - -### Minor Changes - -- c1dc2a4: Deprecate bubbling `model` inputs. -- 1a70e7d: Make Looper model switchable. - -### Patch Changes - -- 3b9229d: Teach Specialist to correctly label the tools array as config. -- Updated dependencies [bbcdd2d] -- Updated dependencies [9ed58cf] -- Updated dependencies [7f2ef33] -- Updated dependencies [bac2e35] -- Updated dependencies [ec2fedd] - - @breadboard-ai/build@0.9.1 - -## 0.10.0 - -### Minor Changes - -- 1a6a9cf: Teach Specialist to ask for a model. -- 78a6bcf: Remove example inputs from gemini-generator -- 494d5ca: Remove examples from Agent Kit components. - -### Patch Changes - -- b201e07: Implement edge-based UI in board-server (and fix a bunch of bugs elsewhere) -- e0dccfe: Add empty text default to Human input. -- Updated dependencies [cc5f4b6] -- Updated dependencies [a940b87] -- Updated dependencies [374ea85] -- Updated dependencies [f93ec06] -- Updated dependencies [398bf4f] -- Updated dependencies [7de241c] - - @breadboard-ai/build@0.9.0 - -## 0.9.1 - -### Patch Changes - -- c5c39be: Internal refactoring (type system) -- Updated dependencies [d88c37b] - - @breadboard-ai/build@0.8.1 - -## 0.9.0 - -### Minor Changes - -- 8d2e618: Teach Human to act as a start node. - -### Patch Changes - -- 8dbbe20: Internal refactoring -- a0852df: Update titles and help links in Core Kit. -- 9a2ffab: Unpin @breadboard-ai/build dependency from being overly constrained -- 1341291: Minor fixes to types and titles. -- Updated dependencies [ad8aa22] -- Updated dependencies [f78ec0a] -- Updated dependencies [2312443] -- Updated dependencies [b76f9a1] -- Updated dependencies [15ae381] - - @breadboard-ai/build@0.8.0 - -## 0.8.1 - -### Patch Changes - -- f4397b9: Update remaining breadboard-web paths - -## 0.8.0 - -### Minor Changes - -- bac5642: Teach Specialist a bit more about joining multiple tool contexts (the "single" mode). -- 16e50fb: Teach Joiner to merge contexts. -- f0b68d0: Teach Human about multimodal inputs. -- b44de19: Teach Specialist to receive LLM Content as tool output. -- 9226f7c: Introduce "Pick One" mode for Human. -- d131307: No longer require property to be named `context`. -- e0eac55: Only show choices when Human is in "choice" mode. -- b7dab90: Teach Specialist about parallel function calls. -- c52e81d: Skip over metadata when merging contexts. -- 4db3ab7: Teach Specialist to pass context to tools. -- 2ace620: Teach `InspectableGraph.describe` to correctly propagate fixed/flexible bit. - -### Patch Changes - -- f62d4da: Account for `item` in the multiple function-calling results. -- 7840ff9: Don't delete `context` in function calling -- d9b76bd: Pass function args even if there's LLM Content. -- dfc6054: Teach Specialist about boards with no inputs. -- 9bbdfc7: Only add Looper task to the first Specialist after it. -- 5a55b7d: Only ask to choose when there are more than one choices. -- 14cf52b: Update helper text for Agent Kit nodes. -- 295b767: Teach Joiner to assign a role when merging. -- faca485: [Debugger] Fix store provider for nav -- 8e2c44d: Teach Specialist about multi-part functionCalls. - -## 0.7.0 - -### Minor Changes - -- c69f1c5: Teach Looper how to plan and add `responseMimeType` to Gemini API. -- a297d10: Implement "Done" condition support for Looper. -- 3f0ce31: Teach Human to display LLM Content. -- e68c06d: Add a Joiner utility node. -- 3397974: Add `InspectableNode.type()` and start using it. -- 09d8288: Teach Super Worker to use tools. -- 8170942: Teach Looper Node a bit more about planning. -- 7b18cb2: Rename `Super Worker` to `Specialist`. -- d66af7b: Deprecate the Tool Worker. - -### Patch Changes - -- f0409d1: Pass looper tasks to context in Specialist. -- 40ce086: Start passing tasks via metadata. -- 8838ba7: Clean up metadata after a looper run. -- d10f568: Various bug fixes to help looper and specialist work better. -- 74434ea: Teach Looper that step-by-step jobs and until-done jobs are mutually exclusive. - -## 0.6.0 - -### Minor Changes - -- 79909eb: Introduce SuperWorker. - -### Patch Changes - -- fb3f870: Fix a problem with incorrect context appending. -- f2eda0b: Fix lots of bugs around Tool Worker. -- 5d08172: Teach tool worker to properly accumulate context. - -## 0.5.0 - -### Minor Changes - -- 407b726: Switch Tool Worker to use proper board loading (using `curry`). - -## 0.4.0 - -### Minor Changes - -- 76da09d: Early support for voting (yes/no) in Human node. - -### Patch Changes - -- 8be93c8: Make Human more flexible in what kind of Context it accepts. - -## 0.3.0 - -### Minor Changes - -- f005b3b: Introduce `load` API for kits. -- ad5c1be: Introduce Tool Worker node in Agent Kit. -- ff4abd6: Teach Repeater to allow inner worker to exit early. - -### Patch Changes - -- 99446b8: Various quality improvements to schemas and Graph Inspector API. -- decfa29: Introduce `DebuggerGraphProvider`. -- 6e631c4: Load agent-kit via manifest dynamically. -- eabd97b: Introduce the concept of log levels in Run Inspector API. -- 8d9bba9: Add better metadata for Agent Kit. -- b1fc53b: Teach `breadboard debug` to load PaLM Kit dynamically. - -## 0.2.0 - -### Minor Changes - -- 73455ce: Implement "human" node in Agent Kit - -## 0.1.0 - -### Minor Changes - -- a9daeda: Introduce Repeater node in Agent Kit. -- a4146c4: Introduce "Agent Kit" to the Breadboard Kit family. -- 5221586: Add "Structured Worker" node to Agent Kit. -- c3966d3: Improve 'Worker' to take instructions and accept string as context. -- 0085ee2: Teach inspector API to correctly describe nodes. -- f06f400: Introduce Agent Kit. - -### Patch Changes - -- 0c2e494: Add 'Summarizer' board illustrating Agent Kit. -- b944657: Update existing boards to use Structured Worker. -- 56ccae5: Introduce a way to inspect kits. -- e9696df: Teach Agent Kit to describe its nodes automatically. diff --git a/packages/agent-kit/README.md b/packages/agent-kit/README.md deleted file mode 100644 index 697a3adddeb..00000000000 --- a/packages/agent-kit/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Breadboard Agent Kit - -This is a collection of Breadboard nodes that facilitates building agent-like experiences. diff --git a/packages/agent-kit/agent.kit.json b/packages/agent-kit/agent.kit.json deleted file mode 100644 index 0214fdce1eb..00000000000 --- a/packages/agent-kit/agent.kit.json +++ /dev/null @@ -1,17770 +0,0 @@ -{ - "title": "Agent Kit", - "description": "A collection of nodes for building Agent-like experiences.", - "version": "0.0.1", - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json", - "nodes": { - "human": { - "title": "Human", - "description": "A human in the loop. Use this node to insert a real person (user input) into your team of synthetic workers.", - "version": "0.0.1", - "metadata": { - "icon": "human", - "help": { - "url": "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#human" - } - }, - "edges": [ - { - "from": "appendContext", - "to": "output-0", - "out": "context", - "in": "context" - }, - { - "from": "areWeDoneChecker", - "to": "doneOutput", - "out": "done", - "in": "context" - }, - { - "from": "areWeDoneChecker", - "to": "routeByMode", - "out": "context", - "in": "context" - }, - { - "from": "buildChooseSchema", - "to": "chooseInput", - "out": "schema", - "in": "schema" - }, - { - "from": "buildChooseSchema", - "to": "pickChoice", - "out": "total", - "in": "total" - }, - { - "from": "chooseInput", - "to": "pickChoice", - "out": "choice", - "in": "choice" - }, - { - "from": "createSchema", - "to": "input", - "out": "schema", - "in": "schema" - }, - { - "from": "input", - "to": "appendContext", - "out": "text", - "in": "toAdd" - }, - { - "from": "input", - "to": "output-0", - "out": "text", - "in": "text" - }, - { - "from": "input-0", - "to": "areWeDoneChecker", - "out": "context", - "in": "context" - }, - { - "from": "input-0", - "to": "buildChooseSchema", - "out": "description", - "in": "description" - }, - { - "from": "input-0", - "to": "buildChooseSchema", - "out": "title", - "in": "title" - }, - { - "from": "input-0", - "to": "createSchema", - "out": "description", - "in": "description" - }, - { - "from": "input-0", - "to": "createSchema", - "out": "title", - "in": "title" - }, - { - "from": "pickChoice", - "to": "choiceOutput", - "out": "context", - "in": "context" - }, - { - "from": "routeByMode", - "to": "appendContext", - "out": "input", - "in": "context" - }, - { - "from": "routeByMode", - "to": "buildChooseSchema", - "out": "choose", - "in": "context" - }, - { - "from": "routeByMode", - "to": "createSchema", - "out": "input", - "in": "context" - }, - { - "from": "routeByMode", - "to": "output", - "out": "output", - "in": "output" - }, - { - "from": "routeByMode", - "to": "pickChoice", - "out": "choose", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context in", - "description": "Incoming conversation context", - "default": "[]", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "description": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Description", - "description": "The user's input", - "default": "A request or response" - }, - "title": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Title", - "description": "The user label", - "default": "User" - } - }, - "required": [] - } - } - }, - { - "id": "choiceOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Context out" - } - }, - "required": [ - "context" - ] - } - }, - "metadata": { - "title": "Choice Output", - "description": "Outputting the user's choice" - } - }, - { - "id": "doneOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Context out" - } - }, - "required": [ - "context" - ] - } - }, - "metadata": { - "title": "Done", - "description": "Skipping because we're done" - } - }, - { - "id": "output", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "output": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Output", - "description": "The output to display" - } - }, - "required": [ - "output" - ], - "behavior": [ - "bubble" - ] - } - }, - "metadata": { - "title": "Output", - "description": "Displaying the output to the user." - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Context out" - }, - "text": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "behavior": [ - "deprecated" - ] - } - }, - "required": [ - "context", - "text" - ] - } - } - }, - { - "id": "appendContext", - "type": "runJavascript", - "configuration": { - "code": "const appendContext = ({context,toAdd})=>{if(!context)throw new Error(\"Context is required\");const existing=Array.isArray(context)?context:[context];const incoming=toAdd;if(typeof incoming===\"string\"){return{context:existing}}if(!incoming.parts){const containsUserRole=existing.filter(item=>item.role!==\"model\"&&item.role!==\"$metadata\").length>0;if(!containsUserRole){return{context:[...existing,{role:\"user\",parts:[{text:\"Do your magic\"}]}]}}return{context:existing}}if(!incoming.role){incoming.role=\"user\"}const last=existing[existing.length-1];if(!last){return{context:[incoming]}}if(last.role!==incoming.role){return{context:[...existing,incoming]}}else{const result=structuredClone(existing);const index=result.length-1;result[index].parts.push(...incoming.parts);return{context:result}}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "toAdd": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "appendContext", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Append Context", - "description": "Appending user input to the conversation context" - } - }, - { - "id": "areWeDoneChecker", - "type": "runJavascript", - "configuration": { - "code": "const areWeDoneChecker = ({context:context2})=>{if(!context2)throw new Error(\"Context is required\");let done=false;for(let i=0;i{const c=asContextArray(context2).reverse();const choices=[];for(const item of c){if(item.role===\"$metadata\"&&item.type===\"split\"){const type=item.data.type;if(type===\"start\"){break}else{choices.push(`Choice ${choices.length+1}`)}}}const schema={type:\"object\",properties:{choice:{title:title2,description:description2,type:\"string\",enum:choices}}};return{schema,total:choices.length};function asContextArray(context3){return Array.isArray(context3)?context3:[context3]}__name(asContextArray,\"asContextArray\")};", - "inputSchema": { - "type": "object", - "properties": { - "title": { - "type": "string", - "behavior": [ - "config" - ] - }, - "description": { - "type": "string", - "behavior": [ - "config" - ] - }, - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "name": "buildChooseSchema", - "outputSchema": { - "type": "object", - "properties": { - "total": { - "type": "number" - }, - "schema": { - "type": "object", - "behavior": [ - "json-schema" - ], - "properties": {}, - "required": [], - "additionalProperties": true - } - } - }, - "raw": true - }, - "metadata": { - "title": "Choose Options", - "description": "Creating the options to choose from" - } - }, - { - "id": "chooseInput", - "type": "input", - "configuration": {}, - "metadata": { - "title": "Look at the choices above and pick one", - "description": "Asking user to choose an option" - } - }, - { - "id": "createSchema", - "type": "runJavascript", - "configuration": { - "code": "const createSchema = ({title:title2,description:description2})=>{const text={title:title2,description:description2,type:\"object\",behavior:[\"transient\",\"llm-content\"],examples:[JSON.stringify({parts:[{text:\"\"}]})]};const schema={type:\"object\",properties:{text}};return{schema}};", - "inputSchema": { - "type": "object", - "properties": { - "title": { - "type": "string", - "behavior": [ - "config" - ] - }, - "description": { - "type": "string", - "behavior": [ - "config" - ] - }, - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "name": "createSchema", - "outputSchema": { - "type": "object", - "properties": { - "schema": { - "type": "object", - "behavior": [ - "json-schema" - ], - "properties": {}, - "required": [], - "additionalProperties": true - } - } - }, - "raw": true - }, - "metadata": { - "title": "Create Schema", - "description": "Creating a schema for user input" - } - }, - { - "id": "input", - "type": "input", - "configuration": {}, - "metadata": { - "title": "Input", - "description": "Asking user for input" - } - }, - { - "id": "pickChoice", - "type": "runJavascript", - "configuration": { - "code": "const pickChoice = ({context:context2,choice,total})=>{const chosenIndex=total-parseInt(choice.split(\" \")[1],10);const c=context2.reverse();const current=[];let found=\"before\";let chunkIndex=0;let startIndex=0;for(const[i,item]of c.entries()){if(item.role===\"$metadata\"&&item.type===\"split\"){const type=item.data.type;if(type===\"start\"){startIndex=i;break}else{if(chunkIndex===chosenIndex){found=\"found\"}else if(chunkIndex>chosenIndex){found=\"after\"}else{found=\"before\"}chunkIndex++}}else if(found===\"found\"){current.push(item)}}const preamble=c.slice(startIndex+1).reverse();if(!found){throw new Error(`Integrity error: choice \"${choice}\" not found`)}return{context:[...preamble,...current.reverse()]}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "choice": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - }, - "total": { - "type": "number" - } - } - }, - "name": "pickChoice", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Read Choice", - "description": "Reading the user's choice" - } - }, - { - "id": "routeByMode", - "type": "runJavascript", - "configuration": { - "code": "const routeByMode = ({context:context2})=>{if(!context2){return{input:[]}}const c=asContextArray(context2);const mode=computeMode(c);if(mode===\"input\"){return{input:c}}else if(mode===\"inputOutput\"){return{input:c,output:c}}return{output:onlyChoices(c),choose:c};function asContextArray(context3){const input2=context3;return Array.isArray(input2)?input2:[input2]}__name(asContextArray,\"asContextArray\");function onlyChoices(context3){const choices=[];const reversed=[...context3].reverse();for(const item of reversed){choices.push(item);if(item.role===\"$metadata\"&&item.type===\"split\"&&item.data.type===\"start\"){break}}return choices.reverse()}__name(onlyChoices,\"onlyChoices\");function computeMode(context3){const lastItem=context3[context3.length-1];if(!lastItem){return\"input\"}if(lastItem.role===\"user\"){return\"input\"}if(lastItem.role!==\"$metadata\"){return\"inputOutput\"}if(lastItem.type===\"split\"&&lastItem.data.type===\"end\"){const splitId=lastItem.data.id;let choiceCounter=1;for(let i=context3.length-2;i>=0;i--){const item=context3[i];if(item.role===\"$metadata\"&&item.type===\"split\"){const{id,type}=item.data;if(splitId!==id){return\"inputOutput\"}if(type===\"start\"){break}choiceCounter++}}if(choiceCounter>1){return\"choose\"}}return\"inputOutput\"}__name(computeMode,\"computeMode\")};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "name": "routeByMode", - "outputSchema": { - "type": "object", - "properties": { - "input": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "output": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "choose": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Compute Mode", - "description": "Determining the mode of operation" - } - } - ] - }, - "repeater": { - "title": "Repeater", - "description": "A worker whose job it is to repeat the same thing over and over, until some condition is met or the max count of repetitions is reached.", - "version": "0.0.1", - "metadata": { - "deprecated": true - }, - "edges": [ - { - "from": "input-0", - "to": "invoke-0", - "out": "context", - "in": "context" - }, - { - "from": "input-0", - "to": "invoke-0", - "out": "worker", - "in": "$board", - "constant": true - }, - { - "from": "input-0", - "to": "runJavascript-0", - "out": "max", - "in": "count" - }, - { - "from": "invoke-0", - "to": "output-0", - "out": "exit", - "in": "context" - }, - { - "from": "invoke-0", - "to": "runJavascript-0", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-0", - "to": "invoke-0", - "out": "continue", - "in": "context" - }, - { - "from": "runJavascript-0", - "to": "output-1", - "out": "stop", - "in": "context" - }, - { - "from": "runJavascript-0", - "to": "runJavascript-0", - "out": "count", - "in": "count" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context", - "description": "Initial conversation context", - "default": "[]", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "max": { - "type": "number", - "title": "Max", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "default": "-1", - "examples": [ - "3" - ] - }, - "worker": { - "type": "object", - "behavior": [ - "board" - ], - "title": "Worker", - "description": "Worker to repeat", - "properties": {}, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "worker" - ] - } - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "context" - ] - } - }, - "metadata": { - "title": "Exit" - } - }, - { - "id": "output-1", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - }, - "required": [ - "context" - ] - } - } - }, - { - "id": "invoke-0", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker" - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context,count})=>{const num=count-1;if(num!==0){return{continue:context,count:num}}return{stop:context}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - }, - "count": { - "type": [ - "number", - "number" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "continue": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "stop": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "count": { - "type": "number" - } - } - }, - "raw": true - }, - "metadata": { - "title": "Counter" - } - } - ] - }, - "structuredWorker": { - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "version": "0.0.1", - "metadata": { - "deprecated": true - }, - "edges": [ - { - "from": "assembleContext", - "to": "output-0", - "out": "context", - "in": "context" - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - }, - { - "from": "input-0", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-0", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-0", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-0", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "output-0", - "out": "json", - "in": "json" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context", - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"the universe within us\"\n }\n ]\n }\n]" - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "instruction": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Instruction", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "format": "multiline" - }, - "schema": { - "type": "object", - "behavior": [ - "json-schema", - "config" - ], - "title": "Schema", - "description": "The schema to convert to schemish.", - "default": "{}", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "required": [ - "instruction" - ] - } - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": [ - "message" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "kind": { - "type": "string" - }, - "error": { - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": [ - "message" - ], - "additionalProperties": false - } - }, - "required": [ - "kind", - "error" - ], - "additionalProperties": false - } - ] - }, - "context": { - "type": "string" - } - }, - "required": [ - "$error", - "context" - ] - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "json": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "JSON", - "description": "The validated JSON." - } - }, - "required": [ - "context", - "json" - ] - } - } - }, - { - "id": "assembleContext", - "type": "runJavascript", - "configuration": { - "code": "const assembleContext = ({context:context2,json})=>{if(!context2)throw new Error(\"Context is required\");return{context:[...context2,{role:\"model\",parts:[{text:JSON.stringify(json)}]}]}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "json": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "assembleContext", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "buildContext", - "type": "runJavascript", - "configuration": { - "code": "const buildContext = ({context:context2,format:format2,instruction:instruction2})=>{if(!Array.isArray(context2)){const text=typeof context2===\"string\"?context2:JSON.stringify(context2);context2=[{role:\"user\",parts:[{text}]}]}const list=context2||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction2},{text:format2});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction2},{text:format2}]}]}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "instruction": { - "type": "string", - "format": "multiline", - "behavior": [ - "config" - ] - }, - "format": { - "type": "string" - } - } - }, - "name": "buildContext", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "count", - "type": "runJavascript", - "configuration": { - "code": "const count = ({context:context2,error,count:count2})=>{const num=count2-1;if(num!=0){return{continue:context2,count:num}}return{stop:error}};", - "inputSchema": { - "type": "object", - "properties": { - "count": { - "anyOf": [ - { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - }, - { - "type": "number" - } - ] - }, - "error": { - "anyOf": [ - { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - }, - { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - ] - }, - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "name": "count", - "outputSchema": { - "type": "object", - "properties": { - "continue": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "count": { - "type": "number" - }, - "stop": { - "type": "string" - } - } - }, - "raw": true - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - } - ] - }, - "specialist": { - "title": "Specialist", - "description": "Given instructions on how to act, makes a single LLM call, optionally invoking tools.", - "version": "2.1.0", - "metadata": { - "icon": "smart-toy", - "help": { - "url": "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#specialist" - }, - "describer": "#subgraph-2" - }, - "edges": [ - { - "from": "assembleBoardInvoke", - "to": "map-0", - "out": "list", - "in": "list" - }, - { - "from": "assembleBoardInvoke", - "to": "runJavascript-0", - "out": "routes", - "in": "routes" - }, - { - "from": "curry-0", - "to": "turnBoardsToFunctions", - "out": "board", - "in": "board" - }, - { - "from": "formatFunctionDeclarations", - "to": "assembleBoardInvoke", - "out": "urlMap", - "in": "urlMap" - }, - { - "from": "formatFunctionDeclarations", - "to": "text-0", - "out": "tools", - "in": "tools" - }, - { - "from": "input-0", - "to": "runJavascript-6", - "out": "*", - "in": "" - }, - { - "from": "input-1", - "to": "turnBoardsToFunctions", - "out": "tools", - "in": "list" - }, - { - "from": "input-2", - "to": "text-0", - "out": "model", - "in": "model" - }, - { - "from": "map-0", - "to": "runJavascript-2", - "out": "list", - "in": "response" - }, - { - "from": "router", - "to": "assembleBoardInvoke", - "out": "context", - "in": "context" - }, - { - "from": "router", - "to": "assembleBoardInvoke", - "out": "functionCalls", - "in": "functionCalls" - }, - { - "from": "router", - "to": "runJavascript-8", - "out": "context", - "in": "generated" - }, - { - "from": "router", - "to": "runJavascript-8", - "out": "text", - "in": "text" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-1", - "to": "runJavascript-0", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-2", - "to": "runJavascript-1", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-3", - "to": "curry-0", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-3", - "to": "runJavascript-2", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-4", - "to": "runJavascript-3", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-4", - "to": "runJavascript-8", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-4", - "to": "text-0", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-5", - "to": "runJavascript-4", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-6", - "to": "formatFunctionDeclarations", - "out": "outs", - "in": "routes" - }, - { - "from": "runJavascript-6", - "to": "runJavascript-5", - "out": "in", - "in": "context" - }, - { - "from": "runJavascript-6", - "to": "runJavascript-5", - "out": "task", - "in": "toAdd" - }, - { - "from": "runJavascript-6", - "to": "runJavascript-7", - "out": "in", - "in": "context" - }, - { - "from": "runJavascript-6", - "to": "text-0", - "out": "persona", - "in": "systemInstruction" - }, - { - "from": "runJavascript-7", - "to": "runJavascript-4", - "out": "progress", - "in": "progress" - }, - { - "from": "runJavascript-8", - "to": "output-1", - "out": "context", - "in": "out" - }, - { - "from": "text-0", - "to": "router", - "out": "context", - "in": "context" - }, - { - "from": "text-0", - "to": "runJavascript-2", - "out": "context", - "in": "generated" - }, - { - "from": "turnBoardsToFunctions", - "to": "formatFunctionDeclarations", - "out": "list", - "in": "list" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "tools": { - "type": "array", - "behavior": [ - "config" - ], - "title": "Tools", - "description": "(Optional) Add tools to this list for the worker to use when needed", - "default": "[]", - "items": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true, - "behavior": [ - "board" - ] - } - } - }, - "required": [] - } - }, - "metadata": { - "title": "Tools Input", - "description": "Specify the tools to use" - } - }, - { - "id": "input-2", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "model": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Model", - "description": "Choose the model to use for this specialist.", - "default": "gemini-1.5-flash-latest", - "examples": [ - "gemini-1.5-flash-latest" - ], - "enum": [ - "gemini-1.5-flash-latest", - "gemini-1.5-pro-latest", - "gemini-1.5-pro-exp-0801", - "gemini-1.5-pro-exp-0827", - "gemini-1.5-flash-8b-exp-0827", - "gemini-1.5-flash-exp-0827" - ] - } - }, - "required": [] - } - }, - "metadata": { - "title": "Model Input", - "description": "Ask which model to use" - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "" - ] - } - }, - "metadata": { - "title": "Tool Output", - "description": "Return tool results as output" - } - }, - { - "id": "output-1", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "out": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Context out" - } - }, - "required": [ - "out" - ] - } - } - }, - { - "id": "assembleBoardInvoke", - "type": "runJavascript", - "configuration": { - "code": "const assembleBoardInvoke = ({functionCalls,urlMap})=>{if(!functionCalls){throw new Error(\"Function call array is a required input\")}if(!urlMap){throw new Error(\"URL map is a required input\")}const calls=functionCalls;if(calls.length===0){throw new Error(\"Function call array must not be empty.\")}const list=[];const routes=[];for(const call of calls){const item=urlMap[call.name];if(!item){throw new Error(`Invalid function call: \"${call.name}\". More than likely, the LLM hallucinated a function call that doesn't exist.`)}if(!item.url){routes.push(call.name);continue}const $board=item.url;const $flags=item.flags;const llmContentProperty=$flags.inputLLMContent||$flags.inputLLMContentArray;const invokeArgs={$board,$flags,...call.args};if(llmContentProperty){const args=call.args;const text=args[llmContentProperty]||\"\";const parts=[{text}];const llmContent={parts,role:\"user\"};if($flags.inputLLMContentArray){invokeArgs[llmContentProperty]=[llmContent]}else{invokeArgs[llmContentProperty]=llmContent}}list.push(invokeArgs)}return{list,routes}};", - "inputSchema": { - "type": "object", - "properties": { - "urlMap": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "flags": { - "type": "object", - "properties": { - "inputLLMContent": { - "type": "string" - }, - "inputLLMContentArray": { - "type": "string" - }, - "outputLLMContent": { - "type": "string" - }, - "outputLLMContentArray": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "url", - "flags" - ], - "additionalProperties": false - } - }, - "context": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - "functionCalls": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - } - } - }, - "name": "assembleBoardInvoke", - "outputSchema": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "type": "object", - "properties": { - "$board": { - "type": "string" - }, - "$flags": { - "type": "object", - "properties": { - "inputLLMContent": { - "type": "string" - }, - "inputLLMContentArray": { - "type": "string" - }, - "outputLLMContent": { - "type": "string" - }, - "outputLLMContentArray": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "$board", - "$flags" - ], - "additionalProperties": true - } - }, - "routes": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Assemble Tool Invoke", - "description": "Assembling tool invocation based on Gemini response" - } - }, - { - "id": "curry-0", - "type": "curry", - "configuration": { - "$board": { - "kind": "board", - "path": "#subgraph-0" - } - }, - "metadata": { - "title": "Add Context", - "description": "Adding context to the board to function converter" - } - }, - { - "id": "formatFunctionDeclarations", - "type": "runJavascript", - "configuration": { - "code": "const formatFunctionDeclarations = ({list,routes})=>{const tools=[];const urlMap={};list.forEach(item=>{tools.push(item.function);const flags=item.flags;urlMap[item.function.name]={url:item.boardURL,flags}});routes.forEach(route=>{tools.push(route);urlMap[route.name]={url:\"\",flags:{}}});return{tools,urlMap}};", - "inputSchema": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "routes": { - "type": "array", - "items": { - "$ref": "#/definitions/def-11" - } - } - } - }, - "name": "formatFunctionDeclarations", - "outputSchema": { - "type": "object", - "properties": { - "tools": { - "type": "array", - "items": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "urlMap": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "flags": { - "type": "object", - "properties": { - "inputLLMContent": { - "type": "string" - }, - "inputLLMContentArray": { - "type": "string" - }, - "outputLLMContent": { - "type": "string" - }, - "outputLLMContentArray": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "url", - "flags" - ], - "additionalProperties": false - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Format Function Declarations", - "description": "Formatting the function declarations" - } - }, - { - "id": "map-0", - "type": "map", - "configuration": { - "board": { - "kind": "board", - "path": "#subgraph-1" - } - }, - "metadata": { - "title": "Invoke Tools in Parallel", - "description": "Invoking tools in parallel" - } - }, - { - "id": "router", - "type": "runJavascript", - "configuration": { - "code": "const router = ({context})=>{if(!context)throw new Error(\"Context is a required input\");const item=context;const functionCallParts=item.parts.filter(part=>\"functionCall\"in part).map(part=>part.functionCall);if(functionCallParts.length===0){const textPart=item.parts.find(part=>\"text\"in part);if(!textPart)throw new Error(\"No text or function call found in context\");return{context,text:textPart.text}}return{context,functionCalls:functionCallParts}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "router", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - "text": { - "type": "string" - }, - "functionCalls": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Router", - "description": "Routing to either function call invocation or text reply" - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context,routes})=>{const out={};let hasRoutes=false;for(const route of routes){out[`p-${route}`]=context;hasRoutes=true}if(!hasRoutes){return{out:context}}for(let i=context.length-1;i>=0;i--){const item=context[i];if(item.role===\"model\"){item.parts=item.parts.filter(part=>!(\"functionCall\"in part));break}}return out};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "routes": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": {} - }, - "raw": true - }, - "metadata": { - "title": "Route Tool Output", - "description": "Routing tool output as needed" - } - }, - { - "id": "runJavascript-1", - "type": "runJavascript", - "configuration": { - "code": "const run = ({merge,...inputs})=>{const entries=Object.entries(inputs).sort();if(merge){const context=[];const parts=[];for(const[,input]of entries){const c=asContextArray(input);let lastIndex=c.length-1;let last;do{last=c[lastIndex--]}while(lastIndex>=0&&last.role===\"$metadata\");if(last){parts.push(...last.parts)}}context.push({parts,role:\"user\"});return{context}}else{let mode;const[f,...rest]=entries;if(!f){return{context:[]}}const first=asContextArray(f[1]);const firstOpenSplits=scanForSplits(first);const preambleIndices=[];for(const[,input]of rest){const c=asContextArray(input);const hasOpenSplits=scanForSplits(c);if(hasOpenSplits){preambleIndices.push(hasOpenSplits[1])}}if(!firstOpenSplits){if(preambleIndices.length===0){mode=\"simple\"}else{mode=\"adhoc\"}}else{const preamblesMatch=preambleIndices.length>0&&preambleIndices.every(value=>value===firstOpenSplits[1]);if(preamblesMatch){mode=\"preamble\"}else{if(firstOpenSplits[1]===first.length-1){mode=\"single\"}else{mode=\"adhoc\"}}}const context=[];if(mode===\"adhoc\"){for(const[,input]of entries){const c=asContextArray(input);context.push(...c)}return{context}}else if(mode===\"simple\"){const splitId=Math.random().toString(36).substring(7);context.push({role:\"$metadata\",type:\"split\",data:{type:\"start\",id:splitId}});for(const[,input]of entries){const c=asContextArray(input);context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}else if(mode===\"preamble\"){const preambleIndex=firstOpenSplits?.[1]||0;const preamble=entries[0][1].slice(0,preambleIndex+1);context.push(...preamble);const splitId=preamble[preamble.length-1].data.id;for(const[,input]of entries){let c=asContextArray(input);if(preambleIndex>=0){c=c.slice(preambleIndex+1)}if(c.length){context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}}else if(mode===\"single\"){const splitId=first[first.length-1].data.id;context.push(...first);for(const[,input]of rest){const c=asContextArray(input);context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}const last=context[context.length-1];last.data.type=\"end\";return{context}}function asContextArray(input){return Array.isArray(input)?input:[input]}__name(asContextArray,\"asContextArray\");function scanForSplits(c){const stack=[];for(const[i,item]of c.entries()){if(item.role!==\"$metadata\")continue;if(item.type!==\"split\")continue;if(item.data.type===\"start\"){stack.push([item.data.id,i])}if(item.data.type===\"end\"){const[id]=stack.pop()||[];if(id!==item.data.id){console.warn(\"Split integrity error: mismatched split start/end markers. Start:\",id,\"End:\",item.data.id);return null}}}return stack.pop()||null}__name(scanForSplits,\"scanForSplits\")};", - "inputSchema": { - "type": "object", - "properties": { - "": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Add Tool Response", - "description": "Adding tool response to context" - } - }, - { - "id": "runJavascript-2", - "type": "runJavascript", - "configuration": { - "code": "const run = ({response,context,generated})=>{const result=Object.fromEntries(response.map((item,i)=>[`context-${i+2}`,item.item]));if(context){result[\"context-0\"]=context}result[\"context-1\"]=[generated];return result};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "response": { - "type": "array", - "items": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "generated": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": {} - }, - "raw": true - }, - "metadata": { - "title": "Format Tool Response", - "description": "Formatting tool response" - } - }, - { - "id": "runJavascript-3", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context})=>{if(!context)throw new Error(\"Context is required\");const c=context;const id=Math.random().toString(36).substring(7);const metadata={role:\"$metadata\",type:\"split\",data:{type:\"start\",id}};return{context:[...c,metadata],id}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Add Split Start", - "description": "Marking the start of parallel processing in the context" - } - }, - { - "id": "runJavascript-4", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context,progress})=>{const contents=Array.isArray(context)?context:[context];const plans=Array.isArray(progress)?progress:[progress];const last=plans[0];if(!last||!last.next){return{context}}const lastLooperMarker=contents.findLastIndex(item=>item.role===\"$metadata\"&&item.type===\"looper\");if(lastLooperMarker>=0){const pastLooper=contents.slice(lastLooperMarker);const hasModel=pastLooper.some(item=>item.role===\"model\");if(hasModel){return{context:contents}}}contents.push({role:\"user\",parts:[{text:last.next}]});return{context:contents}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "progress": { - "type": "array", - "items": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [ - "next" - ], - "additionalProperties": false - } - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Add Looper Task", - "description": "If there is a pending Looper task, add it." - } - }, - { - "id": "runJavascript-5", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context,toAdd})=>{if(!context)throw new Error(\"Context is required\");const existing=Array.isArray(context)?context:[context];const incoming=toAdd;if(typeof incoming===\"string\"){return{context:existing}}if(!incoming.parts){const containsUserRole=existing.filter(item=>item.role!==\"model\"&&item.role!==\"$metadata\").length>0;if(!containsUserRole){return{context:[...existing,{role:\"user\",parts:[{text:\"Do your magic\"}]}]}}return{context:existing}}if(!incoming.role){incoming.role=\"user\"}const last=existing[existing.length-1];if(!last){return{context:[incoming]}}if(last.role!==incoming.role){return{context:[...existing,incoming]}}else{const result=structuredClone(existing);const index=result.length-1;result[index].parts.push(...incoming.parts);return{context:result}}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "looper" - }, - "data": { - "type": "object", - "properties": { - "max": { - "description": "Maximum iterations to make. This can be used to create simple\n\"repeat N times\" loops.", - "type": "number" - }, - "todo": { - "description": "Plan items. Each item represents one trip down the \"Loop\" output, and\nat the end of the list, the \"Context Out\".", - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ] - } - }, - "doneMarker": { - "description": "The marker that will be used by others to signal completion of the job.", - "type": "string" - }, - "done": { - "description": "Indicator that this job is done.", - "type": "boolean" - }, - "appendLast": { - "description": "Whether to append only the last item in the loop to the context or all\nof them.", - "type": "boolean" - }, - "returnLast": { - "description": "Whether to return only last item from the context as the final product\nor all of them;", - "type": "boolean" - }, - "next": { - "description": "The next task.", - "type": "string" - } - } - } - }, - "required": [ - "data", - "type" - ] - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "split" - }, - "data": { - "type": "object", - "properties": { - "type": { - "description": "There are three types of split markers:\n- start: the beginning of the split\n- next: the separator between the split parts\n- end: the end of the split", - "enum": [ - "end", - "next", - "start" - ], - "type": "string" - }, - "id": { - "description": "Unique identifier for the split.", - "type": "string" - } - }, - "required": [ - "id", - "type" - ] - } - }, - "required": [ - "data", - "type" - ] - } - ] - } - ] - } - }, - "toAdd": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "type": "string" - } - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Add Task", - "description": "Adding task to the prompt." - } - }, - { - "id": "runJavascript-6", - "type": "runJavascript", - "configuration": { - "code": "// src/util.ts\n/**\n * @license\n * Copyright 2024 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\nfunction unique(params) {\n return Array.from(new Set(params));\n}\nfunction toId(param) {\n return `p-${param}`;\n}\nfunction isEmptyContent(content) {\n if (!content) return true;\n if (typeof content === \"string\") return true;\n if (!content.parts?.length) return true;\n if (content.parts.length > 1) return false;\n const part = content.parts[0];\n if (!(\"text\" in part)) return true;\n if (part.text.trim() === \"\") return true;\n return false;\n}\nfunction isLLMContent(nodeValue) {\n if (typeof nodeValue !== \"object\" || !nodeValue) return false;\n if (nodeValue === null || nodeValue === void 0) return false;\n if (\"role\" in nodeValue && nodeValue.role === \"$metadata\") {\n return true;\n }\n return \"parts\" in nodeValue && Array.isArray(nodeValue.parts);\n}\nfunction isLLMContentArray(nodeValue) {\n if (!Array.isArray(nodeValue)) return false;\n if (nodeValue.length === 0) return true;\n return isLLMContent(nodeValue.at(-1));\n}\nfunction toTitle(id) {\n const spaced = id?.replace(/[_-]/g, \" \");\n return (spaced?.at(0)?.toUpperCase() ?? \"\") + (spaced?.slice(1)?.toLowerCase() ?? \"\");\n}\n\n// src/js-components/substitute.ts\n/**\n * @license\n * Copyright 2024 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\nfunction run(inputParams) {\n const { in: context = [], persona, task, ...inputs } = inputParams;\n const personaParams = findParams(persona);\n const taskParams = findParams(task);\n const params = mergeParams(personaParams, taskParams);\n const values = collectValues(params, inputs);\n if (context.length === 0 && !task) {\n throw new Error(\n \"Both conversation Context and Task are empty. Specify at least one of them.\"\n );\n }\n return {\n in: context,\n persona: subContent(persona, values),\n task: subContent(task, values),\n outs: collectOuts(personaParams, taskParams)\n };\n}\nfunction collectOuts(...paramsList) {\n const functionNames = unique(\n paramsList.flat().map((param) => {\n const { name, op } = param;\n if (op !== \"out\") return null;\n return name;\n }).filter(Boolean)\n );\n return functionNames.map((name) => {\n const toolName = `TOOL_${name.toLocaleUpperCase()}`;\n return {\n name: toolName,\n description: `Call this function when asked to invoke the \"${toolName}\" tool.`\n };\n });\n}\nfunction findParams(content) {\n const parts = content?.parts;\n if (!parts) return [];\n const results = parts.flatMap((part) => {\n if (!(\"text\" in part)) return [];\n const matches = part.text.matchAll(\n /{{s*(?[w-]+)(?:s*|s*(?[w-]*)(?::s*\"(?[w-]+)\")?)?s*}}/g\n );\n return unique(Array.from(matches)).map((match) => {\n const name = match.groups?.name || \"\";\n const op = match.groups?.op || \"\";\n const arg = match.groups?.arg || \"\";\n if (!name) return null;\n return { name, op, arg, locations: [{ part, parts }] };\n }).filter(Boolean);\n });\n return results;\n}\nfunction mergeParams(...paramList) {\n const result = paramList.reduce((acc, params) => {\n for (const param of params) {\n if (param.op && param.op !== \"in\") {\n continue;\n }\n const { name, locations } = param;\n const existing = acc[name];\n if (existing) {\n existing.push(...locations);\n } else {\n acc[name] = locations;\n }\n }\n return acc;\n }, {});\n return result;\n}\nfunction subContent(content, values) {\n if (Array.isArray(content)) {\n content = content.at(-1);\n }\n if (isEmptyContent(content)) return \"\";\n return {\n role: content.role || \"user\",\n parts: mergeTextParts(\n splitToTemplateParts(content).flatMap((part) => {\n if (\"param\" in part) {\n const { op = \"in\" } = part;\n if (op === \"in\") {\n const value = values[part.param];\n if (typeof value === \"string\") {\n return { text: value };\n } else if (isLLMContent(value)) {\n return value.parts;\n } else if (isLLMContentArray(value)) {\n const last = value.at(-1);\n return last ? last.parts : [];\n } else {\n return { text: JSON.stringify(value) };\n }\n } else {\n return { text: `\"TOOL_${part.param.toLocaleUpperCase()}\"` };\n }\n } else {\n return part;\n }\n })\n )\n };\n}\nfunction mergeTextParts(parts) {\n const merged = [];\n for (const part of parts) {\n if (\"text\" in part) {\n const last = merged[merged.length - 1];\n if (last && \"text\" in last) {\n last.text += part.text;\n } else {\n merged.push(part);\n }\n } else {\n merged.push(part);\n }\n }\n return merged;\n}\nfunction splitToTemplateParts(content) {\n const parts = [];\n for (const part of content.parts) {\n if (!(\"text\" in part)) {\n parts.push(part);\n continue;\n }\n const matches = part.text.matchAll(\n /{{s*(?[w-]+)(?:s*|s*(?[w-]*)(?::s*\"(?[w-]+)\")?)?s*}}/g\n );\n let start = 0;\n for (const match of matches) {\n const name = match.groups?.name || \"\";\n const op = match.groups?.op;\n const arg = match.groups?.arg;\n const end = match.index;\n if (end > start) {\n parts.push({ text: part.text.slice(start, end) });\n }\n parts.push({ param: name, op, arg });\n start = end + match[0].length;\n }\n if (start < part.text.length) {\n parts.push({ text: part.text.slice(start) });\n }\n }\n return parts;\n}\nfunction collectValues(params, inputs) {\n const values = {};\n for (const param in params) {\n const id = toId(param);\n const value = inputs[id];\n if (!value) {\n const title = toTitle(param);\n throw new Error(`Missing required parameter: ${title}`);\n }\n values[param] = value;\n }\n return values;\n}\nexport {\n run\n};\n", - "inputSchema": { - "type": "object", - "properties": { - "in": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "looper" - }, - "data": { - "type": "object", - "properties": { - "max": { - "description": "Maximum iterations to make. This can be used to create simple\n\"repeat N times\" loops.", - "type": "number" - }, - "todo": { - "description": "Plan items. Each item represents one trip down the \"Loop\" output, and\nat the end of the list, the \"Context Out\".", - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ] - } - }, - "doneMarker": { - "description": "The marker that will be used by others to signal completion of the job.", - "type": "string" - }, - "done": { - "description": "Indicator that this job is done.", - "type": "boolean" - }, - "appendLast": { - "description": "Whether to append only the last item in the loop to the context or all\nof them.", - "type": "boolean" - }, - "returnLast": { - "description": "Whether to return only last item from the context as the final product\nor all of them;", - "type": "boolean" - }, - "next": { - "description": "The next task.", - "type": "string" - } - } - } - }, - "required": [ - "data", - "type" - ] - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "split" - }, - "data": { - "type": "object", - "properties": { - "type": { - "description": "There are three types of split markers:\n- start: the beginning of the split\n- next: the separator between the split parts\n- end: the end of the split", - "enum": [ - "end", - "next", - "start" - ], - "type": "string" - }, - "id": { - "description": "Unique identifier for the split.", - "type": "string" - } - }, - "required": [ - "id", - "type" - ] - } - }, - "required": [ - "data", - "type" - ] - } - ] - } - ] - } - }, - "persona": { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - "task": { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "in": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "looper" - }, - "data": { - "type": "object", - "properties": { - "max": { - "description": "Maximum iterations to make. This can be used to create simple\n\"repeat N times\" loops.", - "type": "number" - }, - "todo": { - "description": "Plan items. Each item represents one trip down the \"Loop\" output, and\nat the end of the list, the \"Context Out\".", - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ] - } - }, - "doneMarker": { - "description": "The marker that will be used by others to signal completion of the job.", - "type": "string" - }, - "done": { - "description": "Indicator that this job is done.", - "type": "boolean" - }, - "appendLast": { - "description": "Whether to append only the last item in the loop to the context or all\nof them.", - "type": "boolean" - }, - "returnLast": { - "description": "Whether to return only last item from the context as the final product\nor all of them;", - "type": "boolean" - }, - "next": { - "description": "The next task.", - "type": "string" - } - } - } - }, - "required": [ - "data", - "type" - ] - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "split" - }, - "data": { - "type": "object", - "properties": { - "type": { - "description": "There are three types of split markers:\n- start: the beginning of the split\n- next: the separator between the split parts\n- end: the end of the split", - "enum": [ - "end", - "next", - "start" - ], - "type": "string" - }, - "id": { - "description": "Unique identifier for the split.", - "type": "string" - } - }, - "required": [ - "id", - "type" - ] - } - }, - "required": [ - "data", - "type" - ] - } - ] - } - ] - } - }, - "persona": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "type": "string" - } - ] - }, - "task": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "type": "string" - } - ] - }, - "outs": { - "type": "array", - "items": { - "$ref": "#/definitions/def-11" - } - } - }, - "required": [ - "in", - "outs", - "persona", - "task" - ], - "definitions": { - "def-11": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "parameters": { - "$ref": "#/definitions/def-14" - } - }, - "required": [ - "name" - ] - }, - "def-14": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "type": { - "anyOf": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "string" - } - ] - }, - "properties": { - "type": "object" - }, - "required": { - "type": "array", - "items": { - "type": "string" - } - }, - "format": { - "type": "string" - }, - "behavior": { - "description": "Can be used to provide additional hints to the UI or to other parts of\nthe system about behavior of this particular input/output or input/output\nport.", - "type": "array", - "items": { - "enum": [ - "board", - "bubble", - "code", - "config", - "deprecated", - "error", - "google-drive-file-id", - "google-drive-query", - "image", - "json-schema", - "llm-content", - "ports-spec", - "stream", - "transient" - ], - "type": "string" - } - }, - "transient": { - "type": "boolean" - }, - "enum": { - "type": "array", - "items": { - "type": "string" - } - }, - "default": { - "description": "The default value of the schema. The UI can use this to pre-populate a\nfield with a value, if there is no `examples` present.", - "type": "string" - }, - "additionalProperties": { - "anyOf": [ - { - "$ref": "#/definitions/def-14" - }, - { - "type": "boolean" - } - ] - }, - "items": { - "anyOf": [ - { - "$ref": "#/definitions/def-14" - }, - { - "type": "array", - "items": { - "$ref": "#/definitions/def-14" - } - } - ] - }, - "minItems": { - "type": "number" - }, - "examples": { - "description": "Can be used by UI to pre-populate a field with a value that could be\nused as an example.", - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Substitute Parameters", - "description": "Performing parameter substitution, if needed." - } - }, - { - "id": "runJavascript-7", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context,forkOutputs})=>{const fork=forkOutputs;const existing=Array.isArray(context)?context:[context];const progress=[];for(let i=existing.length-1;i>=0;i--){const item=existing[i];if(item.role===\"$metadata\"&&item.type===\"looper\"){progress.push(item.data)}}if(fork){if(progress.length){return{progress}}else{return{context}}}else{return{context,progress}}};", - "forkOutputs": false, - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "looper" - }, - "data": { - "type": "object", - "properties": { - "max": { - "description": "Maximum iterations to make. This can be used to create simple\n\"repeat N times\" loops.", - "type": "number" - }, - "todo": { - "description": "Plan items. Each item represents one trip down the \"Loop\" output, and\nat the end of the list, the \"Context Out\".", - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ] - } - }, - "doneMarker": { - "description": "The marker that will be used by others to signal completion of the job.", - "type": "string" - }, - "done": { - "description": "Indicator that this job is done.", - "type": "boolean" - }, - "appendLast": { - "description": "Whether to append only the last item in the loop to the context or all\nof them.", - "type": "boolean" - }, - "returnLast": { - "description": "Whether to return only last item from the context as the final product\nor all of them;", - "type": "boolean" - }, - "next": { - "description": "The next task.", - "type": "string" - } - } - } - }, - "required": [ - "data", - "type" - ] - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "split" - }, - "data": { - "type": "object", - "properties": { - "type": { - "description": "There are three types of split markers:\n- start: the beginning of the split\n- next: the separator between the split parts\n- end: the end of the split", - "enum": [ - "end", - "next", - "start" - ], - "type": "string" - }, - "id": { - "description": "Unique identifier for the split.", - "type": "string" - } - }, - "required": [ - "id", - "type" - ] - } - }, - "required": [ - "data", - "type" - ] - } - ] - } - ] - } - }, - "forkOutputs": { - "type": "boolean" - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "progress": { - "type": "array", - "items": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [ - "next" - ], - "additionalProperties": false - } - }, - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Read Progress so far" - } - }, - { - "id": "runJavascript-8", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context,generated})=>{if(!context)throw new Error(\"Context is required\");if(!generated)throw new Error(\"Generated is required\");const c=context;const g=generated;let doneMarker=null;for(let i=0;i{const b=board;const inputs=b.nodes.filter(node=>node.type===\"input\")||[];const outputs=b.nodes.filter(node=>node.type===\"output\");if(outputs.length===0){throw new Error(\"No outputs found\")}const inputSchema=inputs[0]?.configuration?.schema||{};const outputSchema=outputs[0].configuration?.schema;if(!outputSchema){throw new Error(\"No output schema found\")}const properties={};const flags={};for(const key in inputSchema.properties){const property=inputSchema.properties[key];const isObject=property.type===\"object\";const isArray=property.type===\"array\";const type=isObject||isArray?\"string\":property.type;if(isObject&&property.behavior?.includes(\"llm-content\")){flags.inputLLMContent=key}else if(isArray&&property.items?.behavior?.includes(\"llm-content\")){flags.inputLLMContentArray=key;continue}const description2=property.description||property.title||\"text\";properties[key]={type,description:description2}}if(flags.inputLLMContentArray){if(flags.inputLLMContentArray!==\"context\"){const c=b.args?.context;if(c){b.args??={};b.args[flags.inputLLMContentArray]=c;delete b.args.context}}}else{delete b.args?.context}for(const key in outputSchema.properties){const property=outputSchema.properties[key];const isObject=property.type===\"object\";const isArray=property.type===\"array\";if(isObject&&property.behavior?.includes(\"llm-content\")){flags.outputLLMContent=key}else if(isArray&&property.items?.behavior?.includes(\"llm-content\")){flags.outputLLMContentArray=key}}const name=b.title?.replace(/\\W/g,\"_\")||\"function\";const description=b.description;const parameters=Object.entries(properties).length>0?{type:\"object\",properties}:void 0;const f={name,description};if(parameters){f.parameters=parameters}return{function:f,returns:outputSchema,flags,board}};", - "inputSchema": { - "type": "object", - "properties": { - "board": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "function": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "parameters": { - "type": "object", - "behavior": [ - "json-schema" - ], - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "required": [ - "name" - ], - "additionalProperties": false - }, - "board": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true, - "behavior": [ - "board" - ] - }, - "flags": { - "type": "object", - "properties": { - "inputLLMContent": { - "type": "string" - }, - "inputLLMContentArray": { - "type": "string" - }, - "outputLLMContent": { - "type": "string" - }, - "outputLLMContentArray": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - } - }, - "raw": true - }, - "metadata": { - "title": "Get Function Signature from board" - } - } - ] - }, - "subgraph-1": { - "title": "Invoke Board With Args", - "description": "Takes one item of `boardInvocationAssembler` output and invokes it as a board with arguments.", - "version": "0.0.1", - "edges": [ - { - "from": "input-0", - "to": "runJavascript-2", - "out": "item", - "in": "item" - }, - { - "from": "input-0", - "to": "runJavascript-3", - "out": "item", - "in": "item" - }, - { - "from": "invoke-0", - "to": "runJavascript-1", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "item", - "in": "item" - }, - { - "from": "runJavascript-1", - "to": "runJavascript-0", - "out": "result", - "in": "result" - }, - { - "from": "runJavascript-2", - "to": "invoke-0", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-3", - "to": "runJavascript-0", - "out": "flags", - "in": "flags" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": "object", - "properties": { - "$flags": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "$flags" - ], - "additionalProperties": true - } - }, - "required": [ - "item" - ] - } - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "item" - ] - } - } - }, - { - "id": "invoke-0", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke board", - "description": "Invoking the board with unpacked arguments" - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = ({result,flags})=>{let contentDetected=false;const inputs=result;const item=[];const f=flags;if(f){if(f.outputLLMContent){const content=inputs[f.outputLLMContent];content.role=\"tool\";item.push(content);contentDetected=true}else if(f.outputLLMContentArray){const contentArray=inputs[f.outputLLMContentArray];contentArray.forEach(content=>{if(content.role!==\"$metadata\"){content.role=\"tool\"}item.push(content)});contentDetected=true}}else{for(const key in inputs){const input=inputs[key];if(input!==null&&typeof input===\"object\"&&\"content\"in input){const content=input.content;if(content.parts&&Array.isArray(content.parts)){content.role=\"tool\";item.push(content);contentDetected=true}}}}if(!contentDetected){const text=JSON.stringify(inputs);item.push({parts:[{text}],role:\"tool\"})}return{item}};", - "inputSchema": { - "type": "object", - "properties": { - "result": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - }, - "flags": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "item": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "raw": true - }, - "metadata": { - "title": "Format results", - "description": "Formatting results" - } - }, - { - "id": "runJavascript-1", - "type": "runJavascript", - "configuration": { - "code": "const run = result=>({result});", - "inputSchema": { - "type": "object", - "properties": { - "": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "result": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "raw": true - }, - "metadata": { - "title": "Pack results", - "description": "Packing results" - } - }, - { - "id": "runJavascript-2", - "type": "runJavascript", - "configuration": { - "code": "const run = ({item:item2})=>{const{$flags,...result}=item2;return result};", - "inputSchema": { - "type": "object", - "properties": { - "item": { - "type": "object", - "properties": { - "$flags": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "$flags" - ], - "additionalProperties": true - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": {} - }, - "raw": true - }, - "metadata": { - "title": "Unpack args", - "description": "Unpacking board arguments" - } - }, - { - "id": "runJavascript-3", - "type": "runJavascript", - "configuration": { - "code": "const run = ({item:item2})=>{const{$flags}=item2;return{flags:$flags}};", - "inputSchema": { - "type": "object", - "properties": { - "item": { - "type": "object", - "properties": { - "$flags": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "$flags" - ], - "additionalProperties": true - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "flags": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "raw": true - }, - "metadata": { - "title": "Get flags", - "description": "Getting flags for the board invocation" - } - } - ] - }, - "subgraph-2": { - "title": "Specialist Describer", - "description": "A custom describer for the Specialist component", - "version": "0.1.0", - "edges": [ - { - "from": "input-0", - "to": "runJavascript-0", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "inputSchema", - "in": "inputSchema" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "outputSchema", - "in": "outputSchema" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "inputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - }, - "outputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "required": [ - "inputSchema", - "outputSchema" - ] - } - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = function describeSpecialist(inputs){const{$inputSchema,$outputSchema,persona,task}=inputs;const inputSchema={type:\"object\",additionalProperties:false,properties:{...$inputSchema.properties,in:{title:\"Context in\",description:\"Incoming conversation context\",type:\"array\",items:{type:\"object\",behavior:[\"llm-content\"]},examples:[]},task:{title:\"Task\",description:\"(Optional) Provide a specific task with clear instructions for the worker to complete using the conversation context. Use mustache-style {{params}} to add parameters.\",type:\"object\",default:'{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}',behavior:[\"llm-content\",\"config\"],examples:[]},persona:{type:\"object\",behavior:[\"llm-content\",\"config\"],title:\"Persona\",description:\"Describe the worker's skills, capabilities, mindset, and thinking process. Use mustache-style {{params}} to add parameters.\",default:'{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}',examples:[]}},required:[]};const all=[...collectParams(textFromLLMContent(persona)),...collectParams(textFromLLMContent(task))];const params=[];const outs=[];for(const param of all){const{op=\"in\"}=param;if(op===\"in\"){params.push(param.name)}else{outs.push(param.name)}}const inputProps=Object.fromEntries(unique(params).map(param=>[toId(param),{title:toTitle(param),description:`The value to substitute for the parameter \"${param}\"`,type:\"string\"}]));const outputProps=Object.fromEntries(unique(outs).map(param=>[toId(`TOOL_${param.toLocaleUpperCase()}`),{title:toTitle(param),description:`The output chosen when the \"${param}\" tool is invoked`,type:\"string\"}]));const required=params.map(toId);return mergeSchemas(inputSchema,$outputSchema,inputProps,outputProps);function mergeSchemas(inputSchema2,outputSchema,properties,outputProps2){return{inputSchema:{...inputSchema2,properties:{...inputSchema2.properties,...properties},required:[...inputSchema2.required||[],...required]},outputSchema:{...outputSchema,properties:{...outputSchema.properties,...outputProps2}}}}__name(mergeSchemas,\"mergeSchemas\");function toId(param){return`p-${param}`}__name(toId,\"toId\");function toTitle(id){const spaced=id?.replace(/[_-]/g,\" \");return(spaced?.at(0)?.toUpperCase()??\"\")+(spaced?.slice(1)?.toLowerCase()??\"\")}__name(toTitle,\"toTitle\");function textFromLLMContent(content2){return content2?.parts.map(item=>{return\"text\"in item?item.text:\"\"}).join(\"\\n\")||\"\"}__name(textFromLLMContent,\"textFromLLMContent\");function unique(params2){return Array.from(new Set(params2))}__name(unique,\"unique\");function collectParams(text){if(!text)return[];const matches=text.matchAll(/{{\\s*(?[\\w-]+)(?:\\s*\\|\\s*(?[\\w-]*)(?::\\s*\"(?[\\w-]+)\")?)?\\s*}}/g);return Array.from(matches).map(match=>{const name=match.groups?.name||\"\";const op=match.groups?.op;const arg=match.groups?.arg;return{name,op,arg,locations:[]}})}__name(collectParams,\"collectParams\")};", - "inputSchema": { - "type": "object", - "properties": {}, - "additionalProperties": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "inputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - }, - "outputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - }, - "raw": true - }, - "metadata": { - "title": "Describe", - "description": "Describes the Specialist" - } - } - ] - } - } - }, - "worker": { - "title": "Worker", - "description": "The essential Agent building block", - "version": "0.0.1", - "metadata": { - "deprecated": true - }, - "edges": [ - { - "from": "input-0", - "to": "runJavascript-1", - "out": "context", - "in": "context" - }, - { - "from": "input-0", - "to": "runJavascript-1", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-0", - "to": "text-0", - "out": "stopSequences", - "in": "stopSequences" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-1", - "to": "runJavascript-0", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-1", - "to": "text-0", - "out": "context", - "in": "context" - }, - { - "from": "text-0", - "to": "output-0", - "out": "text", - "in": "text" - }, - { - "from": "text-0", - "to": "runJavascript-0", - "out": "context", - "in": "generated" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"the universe within us\"\n }\n ]\n }\n]" - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "instruction": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Instruction", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up a two-line rhyming poem about it.\nLook at the topic below and do your magic" - ], - "format": "multiline" - }, - "stopSequences": { - "type": "array", - "behavior": [ - "config" - ], - "title": "Stop Sequences", - "default": "[]", - "items": { - "type": "string" - } - } - }, - "required": [ - "context", - "instruction" - ] - } - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - } - }, - "required": [ - "context", - "text" - ] - } - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context:context2,generated})=>{if(!context2)throw new Error(\"Context is required\");return{context:[...context2,generated]}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "generated": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Assemble Context" - } - }, - { - "id": "runJavascript-1", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context:context2,instruction:instruction2})=>{if(typeof context2===\"string\"){context2=[{role:\"user\",parts:[{text:context2}]}]}const list=context2??[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction2});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction2}]}]}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "instruction": { - "type": "string", - "format": "multiline", - "behavior": [ - "config" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Build Context" - } - }, - { - "id": "text-0", - "type": "text", - "configuration": {} - } - ] - }, - "looper": { - "title": "Looper", - "description": "A worker whose job it is to repeat the same thing over and over, until some condition is met or the max count of repetitions is reached.", - "version": "0.0.1", - "metadata": { - "icon": "laps", - "help": { - "url": "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#looper" - } - }, - "edges": [ - { - "from": "cleanUp", - "to": "exitOutput", - "out": "context", - "in": "done" - }, - { - "from": "input-1", - "to": "planReader", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "progressReader", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "taskAdder", - "out": "task", - "in": "toAdd" - }, - { - "from": "modelInput", - "to": "planGenerator", - "out": "model", - "in": "model" - }, - { - "from": "planGenerator", - "to": "validateJson", - "out": "text", - "in": "json" - }, - { - "from": "planReader", - "to": "cleanUp", - "out": "done", - "in": "context" - }, - { - "from": "planReader", - "to": "output-2", - "out": "context", - "in": "loop" - }, - { - "from": "progressReader", - "to": "planReader", - "out": "progress", - "in": "progress" - }, - { - "from": "progressReader", - "to": "taskAdder", - "out": "context", - "in": "context" - }, - { - "from": "taskAdder", - "to": "planGenerator", - "out": "context", - "in": "context" - }, - { - "from": "validateJson", - "to": "planReader", - "out": "json", - "in": "progress" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context in", - "description": "Incoming conversation context", - "default": "[]", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "task": { - "type": "object", - "behavior": [ - "llm-content", - "config" - ], - "title": "Task", - "description": "The task to be used for loop planning", - "default": "{\n \"parts\": []\n}", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false - } - }, - "required": [] - } - }, - "metadata": {} - }, - { - "id": "modelInput", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "model": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Model", - "description": "Choose the model to use for this looper.", - "default": "gemini-1.5-flash-latest", - "examples": [ - "gemini-1.5-flash-latest" - ], - "enum": [ - "gemini-1.5-flash-latest", - "gemini-1.5-pro-latest", - "gemini-1.5-pro-exp-0801", - "gemini-1.5-pro-exp-0827", - "gemini-1.5-flash-8b-exp-0827", - "gemini-1.5-flash-exp-0827" - ] - } - }, - "required": [] - } - }, - "metadata": { - "title": "Model Input" - } - }, - { - "id": "exitOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "done": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Done" - } - }, - "required": [ - "done" - ] - } - }, - "metadata": { - "title": "Exit" - } - }, - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "loop": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Loop" - } - }, - "required": [ - "loop" - ] - } - }, - "metadata": {} - }, - { - "id": "cleanUp", - "type": "runJavascript", - "configuration": { - "code": "const cleanUp = ({context:context2})=>{if(!context2)throw new Error(\"Context is required\");return{context:context2.filter(item=>item.role!==\"$metadata\")}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "name": "cleanUp", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Clean up" - } - }, - { - "id": "planGenerator", - "type": "text", - "configuration": { - "responseMimeType": "application/json", - "systemInstruction": "\nYou are to create a precise plan for a given job. This plan will be executed by others and your responsibility is to produce a plan that reflects the job.\n\nYour output must be a valid JSON of the following format:\n\n```json\n{\n \"max\": \"number, optional. Specifies how many iterations to make. Useful when the job specifies the upper limit the number of items in the list.\",\n \"todo\": [{\n \"task\": \"string, The task description. Use action-oriented language, starting with a verb that fits the task.\"\n }]\n \"doneMarker\": \"string, optional. The marker that will be used by others to signal completion.\"\n \"error\": \"string, optional. A description of why you're unable to create a plan\"\n}\n```\n\nThere are four kinds of jobs that you can make plans for.\n\n1) The indefinite job. These are useful when there is not a definite completion condition, and is usually formulated with words like \"indefinitely\" or \"forever\". In such cases, the plan will look like an object without a \"todo\" property, with \"max\" set to a very large number:\n\n```json\n{\n \"max\": 100000000\n}\n```\n\n2) The step-by-step job. These are for situations when a distinct, known number of tasks can be discerned from the job. For example, when asked to write chapters of a book following an outline, there's a clear list of tasks that can be discerned (one \"Write \" per chapter).\n\nA plan for this kind of job will look like an object with \"todo\" items:\n\n```json\n{\n \"todo\": [\n { \"task\": \"\"\n}\n```\n\nCommon markers are \"##STOP##\" or \"##DONE##\", but could be different depending on a job. This type of the job is mutually exclusive with the step-by-step type, so the \"todo\" and \"doneMarker\" may never be specified together.\n\nWhen you are unable to create plan from the job, reply with:\n\n```json\n{\n \"error\": \"\"\n}\n```\n\n" - }, - "metadata": { - "title": "Generating Plan" - } - }, - { - "id": "planReader", - "type": "runJavascript", - "configuration": { - "code": "const planReader = ({context:context2,progress})=>{const plans=Array.isArray(progress)?progress:[progress];const existing=Array.isArray(context2)?context2:[context2];if(!plans||!plans.length){throw new Error(\"Plan is required for Looper to function.\")}try{const current=plans[0];if(current.done){return{done:existing}}const originalPlan=plans[plans.length-1];let max=originalPlan.max;const doneMarker=originalPlan.doneMarker;if(!max){const planItems=originalPlan.todo?.length;if(planItems){max=planItems+1}else{max=Infinity}}const contents=structuredClone(existing);const count=plans.length;if(count>=max){return{done:existing}}if(current.todo&&Array.isArray(current.todo)){const next=current.todo?.shift();if(!next){return{done:existing}}delete current.doneMarker;contents.push({role:\"$metadata\",type:\"looper\",data:{...current,next:next.task}});return{context:contents}}else if(doneMarker){contents.push({role:\"$metadata\",type:\"looper\",data:{doneMarker}});return{context:contents}}else if(max){const count2=plans.length;if(count2>=max){return{done:existing}}contents.push({role:\"$metadata\",type:\"looper\",data:{max}});return{context:contents}}return{done:existing}}catch(e){const error=e;throw new Error(`Invalid plan, unable to proceed: ${error.message}`)}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "progress": { - "anyOf": [ - { - "type": "array", - "items": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - ] - } - } - }, - "name": "planReader", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "done": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Read Plan" - } - }, - { - "id": "progressReader", - "type": "runJavascript", - "configuration": { - "code": "const progressReader = ({context,forkOutputs})=>{const fork=forkOutputs;const existing=Array.isArray(context)?context:[context];const progress=[];for(let i=existing.length-1;i>=0;i--){const item=existing[i];if(item.role===\"$metadata\"&&item.type===\"looper\"){progress.push(item.data)}}if(fork){if(progress.length){return{progress}}else{return{context}}}else{return{context,progress}}};", - "forkOutputs": true, - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "forkOutputs": { - "type": "boolean" - } - } - }, - "name": "progressReader", - "outputSchema": { - "type": "object", - "properties": { - "progress": { - "type": "array", - "items": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Read progress so far" - } - }, - { - "id": "taskAdder", - "type": "runJavascript", - "configuration": { - "code": "const taskAdder = ({context,toAdd})=>{if(!context)throw new Error(\"Context is required\");const existing=Array.isArray(context)?context:[context];const incoming=toAdd;if(typeof incoming===\"string\"){return{context:existing}}if(!incoming.parts){const containsUserRole=existing.filter(item=>item.role!==\"model\"&&item.role!==\"$metadata\").length>0;if(!containsUserRole){return{context:[...existing,{role:\"user\",parts:[{text:\"Do your magic\"}]}]}}return{context:existing}}if(!incoming.role){incoming.role=\"user\"}const last=existing[existing.length-1];if(!last){return{context:[incoming]}}if(last.role!==incoming.role){return{context:[...existing,incoming]}}else{const result=structuredClone(existing);const index=result.length-1;result[index].parts.push(...incoming.parts);return{context:result}}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "toAdd": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content", - "config" - ] - } - } - }, - "name": "taskAdder", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Add Task" - } - }, - { - "id": "validateJson", - "type": "validateJson", - "configuration": { - "schema": { - "type": "object", - "properties": { - "max": { - "type": "number", - "description": "Maximum iterations to make, optional. Default is infinity" - }, - "todo": { - "type": "array", - "description": "Items in the plan, optional. Use this if the plan contains a definite, concrete list of items", - "items": { - "type": "object", - "description": "The object that represent an item in the plan", - "properties": { - "task": { - "type": "string", - "description": "The task description. Use action-oriented language, starting with a verb that fits the task" - } - } - } - }, - "doneMarker": { - "type": "string", - "description": "The marker that will be used by others to signal completion of the job." - }, - "error": { - "type": "string", - "description": "Describe the reason why the plan generation failed" - } - } - } - }, - "metadata": { - "title": "Validate Plan" - } - } - ] - }, - "joiner": { - "title": "Joiner", - "description": "Joins two or more worker contexts into one. Great for combining results of multiple workers.", - "version": "0.0.1", - "metadata": { - "icon": "merge-type", - "help": { - "url": "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#joiner" - } - }, - "edges": [ - { - "from": "input-0", - "to": "runJavascript-0", - "out": "*", - "in": "" - }, - { - "from": "input-0", - "to": "runJavascript-0", - "out": "merge", - "in": "merge" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "merge": { - "type": "boolean", - "behavior": [ - "config" - ], - "title": "Merge Contexts", - "description": "Merge the last items of all incoming conversation into one.", - "default": "false" - } - }, - "required": [], - "additionalProperties": { - "type": "object", - "behavior": [ - "llm-content" - ], - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ] - } - } - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Context out" - } - }, - "required": [ - "context" - ] - } - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = ({merge,...inputs})=>{const entries=Object.entries(inputs).sort();if(merge){const context=[];const parts=[];for(const[,input]of entries){const c=asContextArray(input);let lastIndex=c.length-1;let last;do{last=c[lastIndex--]}while(lastIndex>=0&&last.role===\"$metadata\");if(last){parts.push(...last.parts)}}context.push({parts,role:\"user\"});return{context}}else{let mode;const[f,...rest]=entries;if(!f){return{context:[]}}const first=asContextArray(f[1]);const firstOpenSplits=scanForSplits(first);const preambleIndices=[];for(const[,input]of rest){const c=asContextArray(input);const hasOpenSplits=scanForSplits(c);if(hasOpenSplits){preambleIndices.push(hasOpenSplits[1])}}if(!firstOpenSplits){if(preambleIndices.length===0){mode=\"simple\"}else{mode=\"adhoc\"}}else{const preamblesMatch=preambleIndices.length>0&&preambleIndices.every(value=>value===firstOpenSplits[1]);if(preamblesMatch){mode=\"preamble\"}else{if(firstOpenSplits[1]===first.length-1){mode=\"single\"}else{mode=\"adhoc\"}}}const context=[];if(mode===\"adhoc\"){for(const[,input]of entries){const c=asContextArray(input);context.push(...c)}return{context}}else if(mode===\"simple\"){const splitId=Math.random().toString(36).substring(7);context.push({role:\"$metadata\",type:\"split\",data:{type:\"start\",id:splitId}});for(const[,input]of entries){const c=asContextArray(input);context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}else if(mode===\"preamble\"){const preambleIndex=firstOpenSplits?.[1]||0;const preamble=entries[0][1].slice(0,preambleIndex+1);context.push(...preamble);const splitId=preamble[preamble.length-1].data.id;for(const[,input]of entries){let c=asContextArray(input);if(preambleIndex>=0){c=c.slice(preambleIndex+1)}if(c.length){context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}}else if(mode===\"single\"){const splitId=first[first.length-1].data.id;context.push(...first);for(const[,input]of rest){const c=asContextArray(input);context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}const last=context[context.length-1];last.data.type=\"end\";return{context}}function asContextArray(input){return Array.isArray(input)?input:[input]}__name(asContextArray,\"asContextArray\");function scanForSplits(c){const stack=[];for(const[i,item]of c.entries()){if(item.role!==\"$metadata\")continue;if(item.type!==\"split\")continue;if(item.data.type===\"start\"){stack.push([item.data.id,i])}if(item.data.type===\"end\"){const[id]=stack.pop()||[];if(id!==item.data.id){console.warn(\"Split integrity error: mismatched split start/end markers. Start:\",id,\"End:\",item.data.id);return null}}}return stack.pop()||null}__name(scanForSplits,\"scanForSplits\")};", - "inputSchema": { - "type": "object", - "properties": { - "merge": { - "type": "boolean", - "behavior": [ - "config" - ] - } - }, - "additionalProperties": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - } - } - ] - }, - "content": { - "title": "Content", - "description": "Use it as a way to initialize or add to conversation context, optionally applying extra arguments with mustache-style {{placeholders}}.", - "version": "0.1.0", - "metadata": { - "icon": "code-blocks", - "help": { - "url": "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#content" - }, - "describer": "#subgraph-0" - }, - "edges": [ - { - "from": "input-0", - "to": "runJavascript-0", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - } - } - }, - "required": [ - "context" - ] - } - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = function content(starInputs){const{template,context,...inputs}=starInputs;const params=mergeParams(findParams(template));const values=collectValues(params,inputs);return{context:prependContext(context,subContent(template,values))};function prependContext(context2,c){const content2=isEmptyContent(c)?[]:[c];if(!context2)return[...content2];if(isLLMContentArray(context2)){const last=context2.at(-1);if(last&&last.role===\"user\"){return[...context2.slice(0,-1),{role:\"user\",parts:[...last.parts,...content2.at(0)?.parts||[]]}]}return[...context2,...content2]}return content2}__name(prependContext,\"prependContext\");function isEmptyContent(content2){if(!content2)return true;if(typeof content2===\"string\")return true;if(!content2.parts?.length)return true;if(content2.parts.length>1)return false;const part=content2.parts[0];if(!(\"text\"in part))return true;if(part.text.trim()===\"\")return true;return false}__name(isEmptyContent,\"isEmptyContent\");function subContent(content2,values2){if(Array.isArray(content2)){content2=content2.at(-1)}if(!content2)return\"\";return{role:content2.role||\"user\",parts:mergeTextParts(splitToTemplateParts(content2).flatMap(part=>{if(\"param\"in part){const value=values2[part.param];if(typeof value===\"string\"){return{text:value}}else if(isLLMContent(value)){return value.parts}else if(isLLMContentArray(value)){const last=getLastNonMetadata(value);return last?last.parts:[]}else{return{text:JSON.stringify(value)}}}else{return part}}))}}__name(subContent,\"subContent\");function getLastNonMetadata(content2){for(let i=content2.length-1;i>=0;i--){if(content2[i].role!==\"$metadata\"){return content2[i]}}return null}__name(getLastNonMetadata,\"getLastNonMetadata\");function findParams(content2){const parts=content2?.parts;if(!parts)return[];const results=parts.flatMap(part=>{if(!(\"text\"in part))return[];const matches=part.text.matchAll(/{{\\s*(?[\\w-]+)(?:\\s*\\|\\s*(?[\\w-]*)(?::\\s*\"(?[\\w-]+)\")?)?\\s*}}/g);return unique(Array.from(matches)).map(match=>{const name=match.groups?.name||\"\";if(!name)return null;return{name,locations:[{part,parts}]}}).filter(Boolean)});return results}__name(findParams,\"findParams\");function mergeParams(...paramList){return paramList.reduce((acc,params2)=>{for(const param of params2){const{name,locations}=param;const existing=acc[name];if(existing){existing.push(...locations)}else{acc[name]=locations}}return acc},{})}__name(mergeParams,\"mergeParams\");function unique(params2){return Array.from(new Set(params2))}__name(unique,\"unique\");function mergeTextParts(parts){const merged=[];for(const part of parts){if(\"text\"in part){const last=merged[merged.length-1];if(last&&\"text\"in last){last.text+=part.text}else{merged.push(part)}}else{merged.push(part)}}return merged}__name(mergeTextParts,\"mergeTextParts\");function toId(param){return`p-${param}`}__name(toId,\"toId\");function toTitle(id){const spaced=id?.replace(/[_-]/g,\" \");return(spaced?.at(0)?.toUpperCase()??\"\")+(spaced?.slice(1)?.toLowerCase()??\"\")}__name(toTitle,\"toTitle\");function splitToTemplateParts(content2){const parts=[];for(const part of content2.parts){if(!(\"text\"in part)){parts.push(part);continue}const matches=part.text.matchAll(/{{\\s*(?[\\w-]+)(?:\\s*\\|\\s*(?[\\w-]*)(?::\\s*\"(?[\\w-]+)\")?)?\\s*}}/g);let start=0;for(const match of matches){const name=match.groups?.name||\"\";const end=match.index;if(end>start){parts.push({text:part.text.slice(start,end)})}parts.push({param:name});start=end+match[0].length}if(start[toId(param),{title:toTitle(param),description:`The value to substitute for the parameter \"${param}\"`,type:\"string\"}]));const $inputSchema={properties:{context:{type:\"array\",title:\"Context in\",examples:[],items:{type:\"object\",behavior:[\"llm-content\"]},default:'[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]',description:\"The optional incoming conversation context\"},template:{type:\"object\",title:\"Template\",examples:[],behavior:[\"llm-content\",\"config\"],default:\"null\",description:\"(Optional) Content that will initialize a new conversation contenxt or be appended to the existing one. Use mustache-style {{params}} to add parameters.\"}},type:\"object\",required:[]};const $outputSchema={type:\"object\",properties:{context:{type:\"array\",title:\"Context out\",examples:[],items:{type:\"object\",behavior:[\"llm-content\"]},description:\"The resulting context, created from the template and parameters.\"}},required:[]};const required=params.map(toId);return mergeSchemas($inputSchema,$outputSchema,props);function mergeSchemas(inputSchema,outputSchema,properties){return{inputSchema:{...inputSchema,properties:{...inputSchema.properties,...properties},required:[...inputSchema.required||[],...required]},outputSchema}}__name(mergeSchemas,\"mergeSchemas\");function toId(param){return`p-${param}`}__name(toId,\"toId\");function toTitle(id){const spaced=id?.replace(/[_-]/g,\" \");return(spaced?.at(0)?.toUpperCase()??\"\")+(spaced?.slice(1)?.toLowerCase()??\"\")}__name(toTitle,\"toTitle\");function textFromLLMContent(content2){return content2?.parts.map(item=>{return\"text\"in item?item.text:\"\"}).join(\"\\n\")||\"\"}__name(textFromLLMContent,\"textFromLLMContent\");function unique(params2){return Array.from(new Set(params2))}__name(unique,\"unique\");function collectParams(text){if(!text)return[];const matches=text.matchAll(/{{\\s*(?[\\w-]+)(?:\\s*\\|\\s*(?[\\w-]*)(?::\\s*\"(?[\\w-]+)\")?)?\\s*}}/g);return Array.from(matches).map(match=>match.groups?.name||\"\")}__name(collectParams,\"collectParams\")};", - "inputSchema": { - "type": "object", - "properties": {}, - "additionalProperties": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "inputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - }, - "outputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - }, - "raw": true - }, - "metadata": { - "title": "Describe", - "description": "Describes the content" - } - } - ] - } - } - } - } -} \ No newline at end of file diff --git a/packages/agent-kit/boards/content.bgl.json b/packages/agent-kit/boards/content.bgl.json deleted file mode 100644 index 90d203b63dd..00000000000 --- a/packages/agent-kit/boards/content.bgl.json +++ /dev/null @@ -1,346 +0,0 @@ -{ - "title": "Content", - "description": "Use it as a way to initialize or add to conversation context, optionally applying extra arguments with mustache-style {{placeholders}}.", - "version": "0.1.0", - "metadata": { - "icon": "code-blocks", - "help": { - "url": "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#content" - }, - "describer": "#subgraph-0" - }, - "edges": [ - { - "from": "input-0", - "to": "runJavascript-0", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - } - } - }, - "required": [ - "context" - ] - } - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = function content(starInputs){const{template,context,...inputs}=starInputs;const params=mergeParams(findParams(template));const values=collectValues(params,inputs);return{context:prependContext(context,subContent(template,values))};function prependContext(context2,c){const content2=isEmptyContent(c)?[]:[c];if(!context2)return[...content2];if(isLLMContentArray(context2)){const last=context2.at(-1);if(last&&last.role===\"user\"){return[...context2.slice(0,-1),{role:\"user\",parts:[...last.parts,...content2.at(0)?.parts||[]]}]}return[...context2,...content2]}return content2}__name(prependContext,\"prependContext\");function isEmptyContent(content2){if(!content2)return true;if(typeof content2===\"string\")return true;if(!content2.parts?.length)return true;if(content2.parts.length>1)return false;const part=content2.parts[0];if(!(\"text\"in part))return true;if(part.text.trim()===\"\")return true;return false}__name(isEmptyContent,\"isEmptyContent\");function subContent(content2,values2){if(Array.isArray(content2)){content2=content2.at(-1)}if(!content2)return\"\";return{role:content2.role||\"user\",parts:mergeTextParts(splitToTemplateParts(content2).flatMap(part=>{if(\"param\"in part){const value=values2[part.param];if(typeof value===\"string\"){return{text:value}}else if(isLLMContent(value)){return value.parts}else if(isLLMContentArray(value)){const last=getLastNonMetadata(value);return last?last.parts:[]}else{return{text:JSON.stringify(value)}}}else{return part}}))}}__name(subContent,\"subContent\");function getLastNonMetadata(content2){for(let i=content2.length-1;i>=0;i--){if(content2[i].role!==\"$metadata\"){return content2[i]}}return null}__name(getLastNonMetadata,\"getLastNonMetadata\");function findParams(content2){const parts=content2?.parts;if(!parts)return[];const results=parts.flatMap(part=>{if(!(\"text\"in part))return[];const matches=part.text.matchAll(/{{\\s*(?[\\w-]+)(?:\\s*\\|\\s*(?[\\w-]*)(?::\\s*\"(?[\\w-]+)\")?)?\\s*}}/g);return unique(Array.from(matches)).map(match=>{const name=match.groups?.name||\"\";if(!name)return null;return{name,locations:[{part,parts}]}}).filter(Boolean)});return results}__name(findParams,\"findParams\");function mergeParams(...paramList){return paramList.reduce((acc,params2)=>{for(const param of params2){const{name,locations}=param;const existing=acc[name];if(existing){existing.push(...locations)}else{acc[name]=locations}}return acc},{})}__name(mergeParams,\"mergeParams\");function unique(params2){return Array.from(new Set(params2))}__name(unique,\"unique\");function mergeTextParts(parts){const merged=[];for(const part of parts){if(\"text\"in part){const last=merged[merged.length-1];if(last&&\"text\"in last){last.text+=part.text}else{merged.push(part)}}else{merged.push(part)}}return merged}__name(mergeTextParts,\"mergeTextParts\");function toId(param){return`p-${param}`}__name(toId,\"toId\");function toTitle(id){const spaced=id?.replace(/[_-]/g,\" \");return(spaced?.at(0)?.toUpperCase()??\"\")+(spaced?.slice(1)?.toLowerCase()??\"\")}__name(toTitle,\"toTitle\");function splitToTemplateParts(content2){const parts=[];for(const part of content2.parts){if(!(\"text\"in part)){parts.push(part);continue}const matches=part.text.matchAll(/{{\\s*(?[\\w-]+)(?:\\s*\\|\\s*(?[\\w-]*)(?::\\s*\"(?[\\w-]+)\")?)?\\s*}}/g);let start=0;for(const match of matches){const name=match.groups?.name||\"\";const end=match.index;if(end>start){parts.push({text:part.text.slice(start,end)})}parts.push({param:name});start=end+match[0].length}if(start[toId(param),{title:toTitle(param),description:`The value to substitute for the parameter \"${param}\"`,type:\"string\"}]));const $inputSchema={properties:{context:{type:\"array\",title:\"Context in\",examples:[],items:{type:\"object\",behavior:[\"llm-content\"]},default:'[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]',description:\"The optional incoming conversation context\"},template:{type:\"object\",title:\"Template\",examples:[],behavior:[\"llm-content\",\"config\"],default:\"null\",description:\"(Optional) Content that will initialize a new conversation contenxt or be appended to the existing one. Use mustache-style {{params}} to add parameters.\"}},type:\"object\",required:[]};const $outputSchema={type:\"object\",properties:{context:{type:\"array\",title:\"Context out\",examples:[],items:{type:\"object\",behavior:[\"llm-content\"]},description:\"The resulting context, created from the template and parameters.\"}},required:[]};const required=params.map(toId);return mergeSchemas($inputSchema,$outputSchema,props);function mergeSchemas(inputSchema,outputSchema,properties){return{inputSchema:{...inputSchema,properties:{...inputSchema.properties,...properties},required:[...inputSchema.required||[],...required]},outputSchema}}__name(mergeSchemas,\"mergeSchemas\");function toId(param){return`p-${param}`}__name(toId,\"toId\");function toTitle(id){const spaced=id?.replace(/[_-]/g,\" \");return(spaced?.at(0)?.toUpperCase()??\"\")+(spaced?.slice(1)?.toLowerCase()??\"\")}__name(toTitle,\"toTitle\");function textFromLLMContent(content2){return content2?.parts.map(item=>{return\"text\"in item?item.text:\"\"}).join(\"\\n\")||\"\"}__name(textFromLLMContent,\"textFromLLMContent\");function unique(params2){return Array.from(new Set(params2))}__name(unique,\"unique\");function collectParams(text){if(!text)return[];const matches=text.matchAll(/{{\\s*(?[\\w-]+)(?:\\s*\\|\\s*(?[\\w-]*)(?::\\s*\"(?[\\w-]+)\")?)?\\s*}}/g);return Array.from(matches).map(match=>match.groups?.name||\"\")}__name(collectParams,\"collectParams\")};", - "inputSchema": { - "type": "object", - "properties": {}, - "additionalProperties": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "inputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - }, - "outputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - }, - "raw": true - }, - "metadata": { - "title": "Describe", - "description": "Describes the content" - } - } - ] - } - } -} \ No newline at end of file diff --git a/packages/agent-kit/boards/human.bgl.json b/packages/agent-kit/boards/human.bgl.json deleted file mode 100644 index ebc4309ab01..00000000000 --- a/packages/agent-kit/boards/human.bgl.json +++ /dev/null @@ -1,3956 +0,0 @@ -{ - "title": "Human", - "description": "A human in the loop. Use this node to insert a real person (user input) into your team of synthetic workers.", - "version": "0.0.1", - "metadata": { - "icon": "human", - "help": { - "url": "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#human" - } - }, - "edges": [ - { - "from": "appendContext", - "to": "output-0", - "out": "context", - "in": "context" - }, - { - "from": "areWeDoneChecker", - "to": "doneOutput", - "out": "done", - "in": "context" - }, - { - "from": "areWeDoneChecker", - "to": "routeByMode", - "out": "context", - "in": "context" - }, - { - "from": "buildChooseSchema", - "to": "chooseInput", - "out": "schema", - "in": "schema" - }, - { - "from": "buildChooseSchema", - "to": "pickChoice", - "out": "total", - "in": "total" - }, - { - "from": "chooseInput", - "to": "pickChoice", - "out": "choice", - "in": "choice" - }, - { - "from": "createSchema", - "to": "input", - "out": "schema", - "in": "schema" - }, - { - "from": "input", - "to": "appendContext", - "out": "text", - "in": "toAdd" - }, - { - "from": "input", - "to": "output-0", - "out": "text", - "in": "text" - }, - { - "from": "input-0", - "to": "areWeDoneChecker", - "out": "context", - "in": "context" - }, - { - "from": "input-0", - "to": "buildChooseSchema", - "out": "description", - "in": "description" - }, - { - "from": "input-0", - "to": "buildChooseSchema", - "out": "title", - "in": "title" - }, - { - "from": "input-0", - "to": "createSchema", - "out": "description", - "in": "description" - }, - { - "from": "input-0", - "to": "createSchema", - "out": "title", - "in": "title" - }, - { - "from": "pickChoice", - "to": "choiceOutput", - "out": "context", - "in": "context" - }, - { - "from": "routeByMode", - "to": "appendContext", - "out": "input", - "in": "context" - }, - { - "from": "routeByMode", - "to": "buildChooseSchema", - "out": "choose", - "in": "context" - }, - { - "from": "routeByMode", - "to": "createSchema", - "out": "input", - "in": "context" - }, - { - "from": "routeByMode", - "to": "output", - "out": "output", - "in": "output" - }, - { - "from": "routeByMode", - "to": "pickChoice", - "out": "choose", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context in", - "description": "Incoming conversation context", - "default": "[]", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "description": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Description", - "description": "The user's input", - "default": "A request or response" - }, - "title": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Title", - "description": "The user label", - "default": "User" - } - }, - "required": [] - } - } - }, - { - "id": "choiceOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Context out" - } - }, - "required": [ - "context" - ] - } - }, - "metadata": { - "title": "Choice Output", - "description": "Outputting the user's choice" - } - }, - { - "id": "doneOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Context out" - } - }, - "required": [ - "context" - ] - } - }, - "metadata": { - "title": "Done", - "description": "Skipping because we're done" - } - }, - { - "id": "output", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "output": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Output", - "description": "The output to display" - } - }, - "required": [ - "output" - ], - "behavior": [ - "bubble" - ] - } - }, - "metadata": { - "title": "Output", - "description": "Displaying the output to the user." - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Context out" - }, - "text": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "behavior": [ - "deprecated" - ] - } - }, - "required": [ - "context", - "text" - ] - } - } - }, - { - "id": "appendContext", - "type": "runJavascript", - "configuration": { - "code": "const appendContext = ({context,toAdd})=>{if(!context)throw new Error(\"Context is required\");const existing=Array.isArray(context)?context:[context];const incoming=toAdd;if(typeof incoming===\"string\"){return{context:existing}}if(!incoming.parts){const containsUserRole=existing.filter(item=>item.role!==\"model\"&&item.role!==\"$metadata\").length>0;if(!containsUserRole){return{context:[...existing,{role:\"user\",parts:[{text:\"Do your magic\"}]}]}}return{context:existing}}if(!incoming.role){incoming.role=\"user\"}const last=existing[existing.length-1];if(!last){return{context:[incoming]}}if(last.role!==incoming.role){return{context:[...existing,incoming]}}else{const result=structuredClone(existing);const index=result.length-1;result[index].parts.push(...incoming.parts);return{context:result}}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "toAdd": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "appendContext", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Append Context", - "description": "Appending user input to the conversation context" - } - }, - { - "id": "areWeDoneChecker", - "type": "runJavascript", - "configuration": { - "code": "const areWeDoneChecker = ({context:context2})=>{if(!context2)throw new Error(\"Context is required\");let done=false;for(let i=0;i{const c=asContextArray(context2).reverse();const choices=[];for(const item of c){if(item.role===\"$metadata\"&&item.type===\"split\"){const type=item.data.type;if(type===\"start\"){break}else{choices.push(`Choice ${choices.length+1}`)}}}const schema={type:\"object\",properties:{choice:{title:title2,description:description2,type:\"string\",enum:choices}}};return{schema,total:choices.length};function asContextArray(context3){return Array.isArray(context3)?context3:[context3]}__name(asContextArray,\"asContextArray\")};", - "inputSchema": { - "type": "object", - "properties": { - "title": { - "type": "string", - "behavior": [ - "config" - ] - }, - "description": { - "type": "string", - "behavior": [ - "config" - ] - }, - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "name": "buildChooseSchema", - "outputSchema": { - "type": "object", - "properties": { - "total": { - "type": "number" - }, - "schema": { - "type": "object", - "behavior": [ - "json-schema" - ], - "properties": {}, - "required": [], - "additionalProperties": true - } - } - }, - "raw": true - }, - "metadata": { - "title": "Choose Options", - "description": "Creating the options to choose from" - } - }, - { - "id": "chooseInput", - "type": "input", - "configuration": {}, - "metadata": { - "title": "Look at the choices above and pick one", - "description": "Asking user to choose an option" - } - }, - { - "id": "createSchema", - "type": "runJavascript", - "configuration": { - "code": "const createSchema = ({title:title2,description:description2})=>{const text={title:title2,description:description2,type:\"object\",behavior:[\"transient\",\"llm-content\"],examples:[JSON.stringify({parts:[{text:\"\"}]})]};const schema={type:\"object\",properties:{text}};return{schema}};", - "inputSchema": { - "type": "object", - "properties": { - "title": { - "type": "string", - "behavior": [ - "config" - ] - }, - "description": { - "type": "string", - "behavior": [ - "config" - ] - }, - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "name": "createSchema", - "outputSchema": { - "type": "object", - "properties": { - "schema": { - "type": "object", - "behavior": [ - "json-schema" - ], - "properties": {}, - "required": [], - "additionalProperties": true - } - } - }, - "raw": true - }, - "metadata": { - "title": "Create Schema", - "description": "Creating a schema for user input" - } - }, - { - "id": "input", - "type": "input", - "configuration": {}, - "metadata": { - "title": "Input", - "description": "Asking user for input" - } - }, - { - "id": "pickChoice", - "type": "runJavascript", - "configuration": { - "code": "const pickChoice = ({context:context2,choice,total})=>{const chosenIndex=total-parseInt(choice.split(\" \")[1],10);const c=context2.reverse();const current=[];let found=\"before\";let chunkIndex=0;let startIndex=0;for(const[i,item]of c.entries()){if(item.role===\"$metadata\"&&item.type===\"split\"){const type=item.data.type;if(type===\"start\"){startIndex=i;break}else{if(chunkIndex===chosenIndex){found=\"found\"}else if(chunkIndex>chosenIndex){found=\"after\"}else{found=\"before\"}chunkIndex++}}else if(found===\"found\"){current.push(item)}}const preamble=c.slice(startIndex+1).reverse();if(!found){throw new Error(`Integrity error: choice \"${choice}\" not found`)}return{context:[...preamble,...current.reverse()]}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "choice": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - }, - "total": { - "type": "number" - } - } - }, - "name": "pickChoice", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Read Choice", - "description": "Reading the user's choice" - } - }, - { - "id": "routeByMode", - "type": "runJavascript", - "configuration": { - "code": "const routeByMode = ({context:context2})=>{if(!context2){return{input:[]}}const c=asContextArray(context2);const mode=computeMode(c);if(mode===\"input\"){return{input:c}}else if(mode===\"inputOutput\"){return{input:c,output:c}}return{output:onlyChoices(c),choose:c};function asContextArray(context3){const input2=context3;return Array.isArray(input2)?input2:[input2]}__name(asContextArray,\"asContextArray\");function onlyChoices(context3){const choices=[];const reversed=[...context3].reverse();for(const item of reversed){choices.push(item);if(item.role===\"$metadata\"&&item.type===\"split\"&&item.data.type===\"start\"){break}}return choices.reverse()}__name(onlyChoices,\"onlyChoices\");function computeMode(context3){const lastItem=context3[context3.length-1];if(!lastItem){return\"input\"}if(lastItem.role===\"user\"){return\"input\"}if(lastItem.role!==\"$metadata\"){return\"inputOutput\"}if(lastItem.type===\"split\"&&lastItem.data.type===\"end\"){const splitId=lastItem.data.id;let choiceCounter=1;for(let i=context3.length-2;i>=0;i--){const item=context3[i];if(item.role===\"$metadata\"&&item.type===\"split\"){const{id,type}=item.data;if(splitId!==id){return\"inputOutput\"}if(type===\"start\"){break}choiceCounter++}}if(choiceCounter>1){return\"choose\"}}return\"inputOutput\"}__name(computeMode,\"computeMode\")};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "name": "routeByMode", - "outputSchema": { - "type": "object", - "properties": { - "input": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "output": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "choose": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Compute Mode", - "description": "Determining the mode of operation" - } - } - ] -} \ No newline at end of file diff --git a/packages/agent-kit/boards/joiner.bgl.json b/packages/agent-kit/boards/joiner.bgl.json deleted file mode 100644 index 7ac6c46911c..00000000000 --- a/packages/agent-kit/boards/joiner.bgl.json +++ /dev/null @@ -1,860 +0,0 @@ -{ - "title": "Joiner", - "description": "Joins two or more worker contexts into one. Great for combining results of multiple workers.", - "version": "0.0.1", - "metadata": { - "icon": "merge-type", - "help": { - "url": "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#joiner" - } - }, - "edges": [ - { - "from": "input-0", - "to": "runJavascript-0", - "out": "*", - "in": "" - }, - { - "from": "input-0", - "to": "runJavascript-0", - "out": "merge", - "in": "merge" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "merge": { - "type": "boolean", - "behavior": [ - "config" - ], - "title": "Merge Contexts", - "description": "Merge the last items of all incoming conversation into one.", - "default": "false" - } - }, - "required": [], - "additionalProperties": { - "type": "object", - "behavior": [ - "llm-content" - ], - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ] - } - } - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Context out" - } - }, - "required": [ - "context" - ] - } - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = ({merge,...inputs})=>{const entries=Object.entries(inputs).sort();if(merge){const context=[];const parts=[];for(const[,input]of entries){const c=asContextArray(input);let lastIndex=c.length-1;let last;do{last=c[lastIndex--]}while(lastIndex>=0&&last.role===\"$metadata\");if(last){parts.push(...last.parts)}}context.push({parts,role:\"user\"});return{context}}else{let mode;const[f,...rest]=entries;if(!f){return{context:[]}}const first=asContextArray(f[1]);const firstOpenSplits=scanForSplits(first);const preambleIndices=[];for(const[,input]of rest){const c=asContextArray(input);const hasOpenSplits=scanForSplits(c);if(hasOpenSplits){preambleIndices.push(hasOpenSplits[1])}}if(!firstOpenSplits){if(preambleIndices.length===0){mode=\"simple\"}else{mode=\"adhoc\"}}else{const preamblesMatch=preambleIndices.length>0&&preambleIndices.every(value=>value===firstOpenSplits[1]);if(preamblesMatch){mode=\"preamble\"}else{if(firstOpenSplits[1]===first.length-1){mode=\"single\"}else{mode=\"adhoc\"}}}const context=[];if(mode===\"adhoc\"){for(const[,input]of entries){const c=asContextArray(input);context.push(...c)}return{context}}else if(mode===\"simple\"){const splitId=Math.random().toString(36).substring(7);context.push({role:\"$metadata\",type:\"split\",data:{type:\"start\",id:splitId}});for(const[,input]of entries){const c=asContextArray(input);context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}else if(mode===\"preamble\"){const preambleIndex=firstOpenSplits?.[1]||0;const preamble=entries[0][1].slice(0,preambleIndex+1);context.push(...preamble);const splitId=preamble[preamble.length-1].data.id;for(const[,input]of entries){let c=asContextArray(input);if(preambleIndex>=0){c=c.slice(preambleIndex+1)}if(c.length){context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}}else if(mode===\"single\"){const splitId=first[first.length-1].data.id;context.push(...first);for(const[,input]of rest){const c=asContextArray(input);context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}const last=context[context.length-1];last.data.type=\"end\";return{context}}function asContextArray(input){return Array.isArray(input)?input:[input]}__name(asContextArray,\"asContextArray\");function scanForSplits(c){const stack=[];for(const[i,item]of c.entries()){if(item.role!==\"$metadata\")continue;if(item.type!==\"split\")continue;if(item.data.type===\"start\"){stack.push([item.data.id,i])}if(item.data.type===\"end\"){const[id]=stack.pop()||[];if(id!==item.data.id){console.warn(\"Split integrity error: mismatched split start/end markers. Start:\",id,\"End:\",item.data.id);return null}}}return stack.pop()||null}__name(scanForSplits,\"scanForSplits\")};", - "inputSchema": { - "type": "object", - "properties": { - "merge": { - "type": "boolean", - "behavior": [ - "config" - ] - } - }, - "additionalProperties": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - } - } - ] -} \ No newline at end of file diff --git a/packages/agent-kit/boards/looper.bgl.json b/packages/agent-kit/boards/looper.bgl.json deleted file mode 100644 index cc55e119fb4..00000000000 --- a/packages/agent-kit/boards/looper.bgl.json +++ /dev/null @@ -1,2876 +0,0 @@ -{ - "title": "Looper", - "description": "A worker whose job it is to repeat the same thing over and over, until some condition is met or the max count of repetitions is reached.", - "version": "0.0.1", - "metadata": { - "icon": "laps", - "help": { - "url": "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#looper" - } - }, - "edges": [ - { - "from": "cleanUp", - "to": "exitOutput", - "out": "context", - "in": "done" - }, - { - "from": "input-1", - "to": "planReader", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "progressReader", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "taskAdder", - "out": "task", - "in": "toAdd" - }, - { - "from": "modelInput", - "to": "planGenerator", - "out": "model", - "in": "model" - }, - { - "from": "planGenerator", - "to": "validateJson", - "out": "text", - "in": "json" - }, - { - "from": "planReader", - "to": "cleanUp", - "out": "done", - "in": "context" - }, - { - "from": "planReader", - "to": "output-2", - "out": "context", - "in": "loop" - }, - { - "from": "progressReader", - "to": "planReader", - "out": "progress", - "in": "progress" - }, - { - "from": "progressReader", - "to": "taskAdder", - "out": "context", - "in": "context" - }, - { - "from": "taskAdder", - "to": "planGenerator", - "out": "context", - "in": "context" - }, - { - "from": "validateJson", - "to": "planReader", - "out": "json", - "in": "progress" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context in", - "description": "Incoming conversation context", - "default": "[]", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "task": { - "type": "object", - "behavior": [ - "llm-content", - "config" - ], - "title": "Task", - "description": "The task to be used for loop planning", - "default": "{\n \"parts\": []\n}", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false - } - }, - "required": [] - } - }, - "metadata": {} - }, - { - "id": "modelInput", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "model": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Model", - "description": "Choose the model to use for this looper.", - "default": "gemini-1.5-flash-latest", - "examples": [ - "gemini-1.5-flash-latest" - ], - "enum": [ - "gemini-1.5-flash-latest", - "gemini-1.5-pro-latest", - "gemini-1.5-pro-exp-0801", - "gemini-1.5-pro-exp-0827", - "gemini-1.5-flash-8b-exp-0827", - "gemini-1.5-flash-exp-0827" - ] - } - }, - "required": [] - } - }, - "metadata": { - "title": "Model Input" - } - }, - { - "id": "exitOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "done": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Done" - } - }, - "required": [ - "done" - ] - } - }, - "metadata": { - "title": "Exit" - } - }, - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "loop": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Loop" - } - }, - "required": [ - "loop" - ] - } - }, - "metadata": {} - }, - { - "id": "cleanUp", - "type": "runJavascript", - "configuration": { - "code": "const cleanUp = ({context:context2})=>{if(!context2)throw new Error(\"Context is required\");return{context:context2.filter(item=>item.role!==\"$metadata\")}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "name": "cleanUp", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Clean up" - } - }, - { - "id": "planGenerator", - "type": "text", - "configuration": { - "responseMimeType": "application/json", - "systemInstruction": "\nYou are to create a precise plan for a given job. This plan will be executed by others and your responsibility is to produce a plan that reflects the job.\n\nYour output must be a valid JSON of the following format:\n\n```json\n{\n \"max\": \"number, optional. Specifies how many iterations to make. Useful when the job specifies the upper limit the number of items in the list.\",\n \"todo\": [{\n \"task\": \"string, The task description. Use action-oriented language, starting with a verb that fits the task.\"\n }]\n \"doneMarker\": \"string, optional. The marker that will be used by others to signal completion.\"\n \"error\": \"string, optional. A description of why you're unable to create a plan\"\n}\n```\n\nThere are four kinds of jobs that you can make plans for.\n\n1) The indefinite job. These are useful when there is not a definite completion condition, and is usually formulated with words like \"indefinitely\" or \"forever\". In such cases, the plan will look like an object without a \"todo\" property, with \"max\" set to a very large number:\n\n```json\n{\n \"max\": 100000000\n}\n```\n\n2) The step-by-step job. These are for situations when a distinct, known number of tasks can be discerned from the job. For example, when asked to write chapters of a book following an outline, there's a clear list of tasks that can be discerned (one \"Write \" per chapter).\n\nA plan for this kind of job will look like an object with \"todo\" items:\n\n```json\n{\n \"todo\": [\n { \"task\": \"\"\n}\n```\n\nCommon markers are \"##STOP##\" or \"##DONE##\", but could be different depending on a job. This type of the job is mutually exclusive with the step-by-step type, so the \"todo\" and \"doneMarker\" may never be specified together.\n\nWhen you are unable to create plan from the job, reply with:\n\n```json\n{\n \"error\": \"\"\n}\n```\n\n" - }, - "metadata": { - "title": "Generating Plan" - } - }, - { - "id": "planReader", - "type": "runJavascript", - "configuration": { - "code": "const planReader = ({context:context2,progress})=>{const plans=Array.isArray(progress)?progress:[progress];const existing=Array.isArray(context2)?context2:[context2];if(!plans||!plans.length){throw new Error(\"Plan is required for Looper to function.\")}try{const current=plans[0];if(current.done){return{done:existing}}const originalPlan=plans[plans.length-1];let max=originalPlan.max;const doneMarker=originalPlan.doneMarker;if(!max){const planItems=originalPlan.todo?.length;if(planItems){max=planItems+1}else{max=Infinity}}const contents=structuredClone(existing);const count=plans.length;if(count>=max){return{done:existing}}if(current.todo&&Array.isArray(current.todo)){const next=current.todo?.shift();if(!next){return{done:existing}}delete current.doneMarker;contents.push({role:\"$metadata\",type:\"looper\",data:{...current,next:next.task}});return{context:contents}}else if(doneMarker){contents.push({role:\"$metadata\",type:\"looper\",data:{doneMarker}});return{context:contents}}else if(max){const count2=plans.length;if(count2>=max){return{done:existing}}contents.push({role:\"$metadata\",type:\"looper\",data:{max}});return{context:contents}}return{done:existing}}catch(e){const error=e;throw new Error(`Invalid plan, unable to proceed: ${error.message}`)}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "progress": { - "anyOf": [ - { - "type": "array", - "items": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - ] - } - } - }, - "name": "planReader", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "done": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Read Plan" - } - }, - { - "id": "progressReader", - "type": "runJavascript", - "configuration": { - "code": "const progressReader = ({context,forkOutputs})=>{const fork=forkOutputs;const existing=Array.isArray(context)?context:[context];const progress=[];for(let i=existing.length-1;i>=0;i--){const item=existing[i];if(item.role===\"$metadata\"&&item.type===\"looper\"){progress.push(item.data)}}if(fork){if(progress.length){return{progress}}else{return{context}}}else{return{context,progress}}};", - "forkOutputs": true, - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "forkOutputs": { - "type": "boolean" - } - } - }, - "name": "progressReader", - "outputSchema": { - "type": "object", - "properties": { - "progress": { - "type": "array", - "items": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Read progress so far" - } - }, - { - "id": "taskAdder", - "type": "runJavascript", - "configuration": { - "code": "const taskAdder = ({context,toAdd})=>{if(!context)throw new Error(\"Context is required\");const existing=Array.isArray(context)?context:[context];const incoming=toAdd;if(typeof incoming===\"string\"){return{context:existing}}if(!incoming.parts){const containsUserRole=existing.filter(item=>item.role!==\"model\"&&item.role!==\"$metadata\").length>0;if(!containsUserRole){return{context:[...existing,{role:\"user\",parts:[{text:\"Do your magic\"}]}]}}return{context:existing}}if(!incoming.role){incoming.role=\"user\"}const last=existing[existing.length-1];if(!last){return{context:[incoming]}}if(last.role!==incoming.role){return{context:[...existing,incoming]}}else{const result=structuredClone(existing);const index=result.length-1;result[index].parts.push(...incoming.parts);return{context:result}}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "toAdd": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content", - "config" - ] - } - } - }, - "name": "taskAdder", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Add Task" - } - }, - { - "id": "validateJson", - "type": "validateJson", - "configuration": { - "schema": { - "type": "object", - "properties": { - "max": { - "type": "number", - "description": "Maximum iterations to make, optional. Default is infinity" - }, - "todo": { - "type": "array", - "description": "Items in the plan, optional. Use this if the plan contains a definite, concrete list of items", - "items": { - "type": "object", - "description": "The object that represent an item in the plan", - "properties": { - "task": { - "type": "string", - "description": "The task description. Use action-oriented language, starting with a verb that fits the task" - } - } - } - }, - "doneMarker": { - "type": "string", - "description": "The marker that will be used by others to signal completion of the job." - }, - "error": { - "type": "string", - "description": "Describe the reason why the plan generation failed" - } - } - } - }, - "metadata": { - "title": "Validate Plan" - } - } - ] -} \ No newline at end of file diff --git a/packages/agent-kit/boards/specialist.bgl.json b/packages/agent-kit/boards/specialist.bgl.json deleted file mode 100644 index 0f626bc49b7..00000000000 --- a/packages/agent-kit/boards/specialist.bgl.json +++ /dev/null @@ -1,5420 +0,0 @@ -{ - "title": "Specialist", - "description": "Given instructions on how to act, makes a single LLM call, optionally invoking tools.", - "version": "2.1.0", - "metadata": { - "icon": "smart-toy", - "help": { - "url": "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#specialist" - }, - "describer": "#subgraph-2" - }, - "edges": [ - { - "from": "assembleBoardInvoke", - "to": "map-0", - "out": "list", - "in": "list" - }, - { - "from": "assembleBoardInvoke", - "to": "runJavascript-0", - "out": "routes", - "in": "routes" - }, - { - "from": "curry-0", - "to": "turnBoardsToFunctions", - "out": "board", - "in": "board" - }, - { - "from": "formatFunctionDeclarations", - "to": "assembleBoardInvoke", - "out": "urlMap", - "in": "urlMap" - }, - { - "from": "formatFunctionDeclarations", - "to": "text-0", - "out": "tools", - "in": "tools" - }, - { - "from": "input-0", - "to": "runJavascript-6", - "out": "*", - "in": "" - }, - { - "from": "input-1", - "to": "turnBoardsToFunctions", - "out": "tools", - "in": "list" - }, - { - "from": "input-2", - "to": "text-0", - "out": "model", - "in": "model" - }, - { - "from": "map-0", - "to": "runJavascript-2", - "out": "list", - "in": "response" - }, - { - "from": "router", - "to": "assembleBoardInvoke", - "out": "context", - "in": "context" - }, - { - "from": "router", - "to": "assembleBoardInvoke", - "out": "functionCalls", - "in": "functionCalls" - }, - { - "from": "router", - "to": "runJavascript-8", - "out": "context", - "in": "generated" - }, - { - "from": "router", - "to": "runJavascript-8", - "out": "text", - "in": "text" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-1", - "to": "runJavascript-0", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-2", - "to": "runJavascript-1", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-3", - "to": "curry-0", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-3", - "to": "runJavascript-2", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-4", - "to": "runJavascript-3", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-4", - "to": "runJavascript-8", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-4", - "to": "text-0", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-5", - "to": "runJavascript-4", - "out": "context", - "in": "context" - }, - { - "from": "runJavascript-6", - "to": "formatFunctionDeclarations", - "out": "outs", - "in": "routes" - }, - { - "from": "runJavascript-6", - "to": "runJavascript-5", - "out": "in", - "in": "context" - }, - { - "from": "runJavascript-6", - "to": "runJavascript-5", - "out": "task", - "in": "toAdd" - }, - { - "from": "runJavascript-6", - "to": "runJavascript-7", - "out": "in", - "in": "context" - }, - { - "from": "runJavascript-6", - "to": "text-0", - "out": "persona", - "in": "systemInstruction" - }, - { - "from": "runJavascript-7", - "to": "runJavascript-4", - "out": "progress", - "in": "progress" - }, - { - "from": "runJavascript-8", - "to": "output-1", - "out": "context", - "in": "out" - }, - { - "from": "text-0", - "to": "router", - "out": "context", - "in": "context" - }, - { - "from": "text-0", - "to": "runJavascript-2", - "out": "context", - "in": "generated" - }, - { - "from": "turnBoardsToFunctions", - "to": "formatFunctionDeclarations", - "out": "list", - "in": "list" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "tools": { - "type": "array", - "behavior": [ - "config" - ], - "title": "Tools", - "description": "(Optional) Add tools to this list for the worker to use when needed", - "default": "[]", - "items": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true, - "behavior": [ - "board" - ] - } - } - }, - "required": [] - } - }, - "metadata": { - "title": "Tools Input", - "description": "Specify the tools to use" - } - }, - { - "id": "input-2", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "model": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Model", - "description": "Choose the model to use for this specialist.", - "default": "gemini-1.5-flash-latest", - "examples": [ - "gemini-1.5-flash-latest" - ], - "enum": [ - "gemini-1.5-flash-latest", - "gemini-1.5-pro-latest", - "gemini-1.5-pro-exp-0801", - "gemini-1.5-pro-exp-0827", - "gemini-1.5-flash-8b-exp-0827", - "gemini-1.5-flash-exp-0827" - ] - } - }, - "required": [] - } - }, - "metadata": { - "title": "Model Input", - "description": "Ask which model to use" - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "" - ] - } - }, - "metadata": { - "title": "Tool Output", - "description": "Return tool results as output" - } - }, - { - "id": "output-1", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "out": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "Context out" - } - }, - "required": [ - "out" - ] - } - } - }, - { - "id": "assembleBoardInvoke", - "type": "runJavascript", - "configuration": { - "code": "const assembleBoardInvoke = ({functionCalls,urlMap})=>{if(!functionCalls){throw new Error(\"Function call array is a required input\")}if(!urlMap){throw new Error(\"URL map is a required input\")}const calls=functionCalls;if(calls.length===0){throw new Error(\"Function call array must not be empty.\")}const list=[];const routes=[];for(const call of calls){const item=urlMap[call.name];if(!item){throw new Error(`Invalid function call: \"${call.name}\". More than likely, the LLM hallucinated a function call that doesn't exist.`)}if(!item.url){routes.push(call.name);continue}const $board=item.url;const $flags=item.flags;const llmContentProperty=$flags.inputLLMContent||$flags.inputLLMContentArray;const invokeArgs={$board,$flags,...call.args};if(llmContentProperty){const args=call.args;const text=args[llmContentProperty]||\"\";const parts=[{text}];const llmContent={parts,role:\"user\"};if($flags.inputLLMContentArray){invokeArgs[llmContentProperty]=[llmContent]}else{invokeArgs[llmContentProperty]=llmContent}}list.push(invokeArgs)}return{list,routes}};", - "inputSchema": { - "type": "object", - "properties": { - "urlMap": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "flags": { - "type": "object", - "properties": { - "inputLLMContent": { - "type": "string" - }, - "inputLLMContentArray": { - "type": "string" - }, - "outputLLMContent": { - "type": "string" - }, - "outputLLMContentArray": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "url", - "flags" - ], - "additionalProperties": false - } - }, - "context": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - "functionCalls": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - } - } - }, - "name": "assembleBoardInvoke", - "outputSchema": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "type": "object", - "properties": { - "$board": { - "type": "string" - }, - "$flags": { - "type": "object", - "properties": { - "inputLLMContent": { - "type": "string" - }, - "inputLLMContentArray": { - "type": "string" - }, - "outputLLMContent": { - "type": "string" - }, - "outputLLMContentArray": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "$board", - "$flags" - ], - "additionalProperties": true - } - }, - "routes": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Assemble Tool Invoke", - "description": "Assembling tool invocation based on Gemini response" - } - }, - { - "id": "curry-0", - "type": "curry", - "configuration": { - "$board": { - "kind": "board", - "path": "#subgraph-0" - } - }, - "metadata": { - "title": "Add Context", - "description": "Adding context to the board to function converter" - } - }, - { - "id": "formatFunctionDeclarations", - "type": "runJavascript", - "configuration": { - "code": "const formatFunctionDeclarations = ({list,routes})=>{const tools=[];const urlMap={};list.forEach(item=>{tools.push(item.function);const flags=item.flags;urlMap[item.function.name]={url:item.boardURL,flags}});routes.forEach(route=>{tools.push(route);urlMap[route.name]={url:\"\",flags:{}}});return{tools,urlMap}};", - "inputSchema": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "routes": { - "type": "array", - "items": { - "$ref": "#/definitions/def-11" - } - } - } - }, - "name": "formatFunctionDeclarations", - "outputSchema": { - "type": "object", - "properties": { - "tools": { - "type": "array", - "items": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "urlMap": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "flags": { - "type": "object", - "properties": { - "inputLLMContent": { - "type": "string" - }, - "inputLLMContentArray": { - "type": "string" - }, - "outputLLMContent": { - "type": "string" - }, - "outputLLMContentArray": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "url", - "flags" - ], - "additionalProperties": false - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Format Function Declarations", - "description": "Formatting the function declarations" - } - }, - { - "id": "map-0", - "type": "map", - "configuration": { - "board": { - "kind": "board", - "path": "#subgraph-1" - } - }, - "metadata": { - "title": "Invoke Tools in Parallel", - "description": "Invoking tools in parallel" - } - }, - { - "id": "router", - "type": "runJavascript", - "configuration": { - "code": "const router = ({context})=>{if(!context)throw new Error(\"Context is a required input\");const item=context;const functionCallParts=item.parts.filter(part=>\"functionCall\"in part).map(part=>part.functionCall);if(functionCallParts.length===0){const textPart=item.parts.find(part=>\"text\"in part);if(!textPart)throw new Error(\"No text or function call found in context\");return{context,text:textPart.text}}return{context,functionCalls:functionCallParts}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "router", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - "text": { - "type": "string" - }, - "functionCalls": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Router", - "description": "Routing to either function call invocation or text reply" - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context,routes})=>{const out={};let hasRoutes=false;for(const route of routes){out[`p-${route}`]=context;hasRoutes=true}if(!hasRoutes){return{out:context}}for(let i=context.length-1;i>=0;i--){const item=context[i];if(item.role===\"model\"){item.parts=item.parts.filter(part=>!(\"functionCall\"in part));break}}return out};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "routes": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": {} - }, - "raw": true - }, - "metadata": { - "title": "Route Tool Output", - "description": "Routing tool output as needed" - } - }, - { - "id": "runJavascript-1", - "type": "runJavascript", - "configuration": { - "code": "const run = ({merge,...inputs})=>{const entries=Object.entries(inputs).sort();if(merge){const context=[];const parts=[];for(const[,input]of entries){const c=asContextArray(input);let lastIndex=c.length-1;let last;do{last=c[lastIndex--]}while(lastIndex>=0&&last.role===\"$metadata\");if(last){parts.push(...last.parts)}}context.push({parts,role:\"user\"});return{context}}else{let mode;const[f,...rest]=entries;if(!f){return{context:[]}}const first=asContextArray(f[1]);const firstOpenSplits=scanForSplits(first);const preambleIndices=[];for(const[,input]of rest){const c=asContextArray(input);const hasOpenSplits=scanForSplits(c);if(hasOpenSplits){preambleIndices.push(hasOpenSplits[1])}}if(!firstOpenSplits){if(preambleIndices.length===0){mode=\"simple\"}else{mode=\"adhoc\"}}else{const preamblesMatch=preambleIndices.length>0&&preambleIndices.every(value=>value===firstOpenSplits[1]);if(preamblesMatch){mode=\"preamble\"}else{if(firstOpenSplits[1]===first.length-1){mode=\"single\"}else{mode=\"adhoc\"}}}const context=[];if(mode===\"adhoc\"){for(const[,input]of entries){const c=asContextArray(input);context.push(...c)}return{context}}else if(mode===\"simple\"){const splitId=Math.random().toString(36).substring(7);context.push({role:\"$metadata\",type:\"split\",data:{type:\"start\",id:splitId}});for(const[,input]of entries){const c=asContextArray(input);context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}else if(mode===\"preamble\"){const preambleIndex=firstOpenSplits?.[1]||0;const preamble=entries[0][1].slice(0,preambleIndex+1);context.push(...preamble);const splitId=preamble[preamble.length-1].data.id;for(const[,input]of entries){let c=asContextArray(input);if(preambleIndex>=0){c=c.slice(preambleIndex+1)}if(c.length){context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}}else if(mode===\"single\"){const splitId=first[first.length-1].data.id;context.push(...first);for(const[,input]of rest){const c=asContextArray(input);context.push(...c);context.push({role:\"$metadata\",type:\"split\",data:{type:\"next\",id:splitId}})}}const last=context[context.length-1];last.data.type=\"end\";return{context}}function asContextArray(input){return Array.isArray(input)?input:[input]}__name(asContextArray,\"asContextArray\");function scanForSplits(c){const stack=[];for(const[i,item]of c.entries()){if(item.role!==\"$metadata\")continue;if(item.type!==\"split\")continue;if(item.data.type===\"start\"){stack.push([item.data.id,i])}if(item.data.type===\"end\"){const[id]=stack.pop()||[];if(id!==item.data.id){console.warn(\"Split integrity error: mismatched split start/end markers. Start:\",id,\"End:\",item.data.id);return null}}}return stack.pop()||null}__name(scanForSplits,\"scanForSplits\")};", - "inputSchema": { - "type": "object", - "properties": { - "": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Add Tool Response", - "description": "Adding tool response to context" - } - }, - { - "id": "runJavascript-2", - "type": "runJavascript", - "configuration": { - "code": "const run = ({response,context,generated})=>{const result=Object.fromEntries(response.map((item,i)=>[`context-${i+2}`,item.item]));if(context){result[\"context-0\"]=context}result[\"context-1\"]=[generated];return result};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "response": { - "type": "array", - "items": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "generated": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": {} - }, - "raw": true - }, - "metadata": { - "title": "Format Tool Response", - "description": "Formatting tool response" - } - }, - { - "id": "runJavascript-3", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context})=>{if(!context)throw new Error(\"Context is required\");const c=context;const id=Math.random().toString(36).substring(7);const metadata={role:\"$metadata\",type:\"split\",data:{type:\"start\",id}};return{context:[...c,metadata],id}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Add Split Start", - "description": "Marking the start of parallel processing in the context" - } - }, - { - "id": "runJavascript-4", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context,progress})=>{const contents=Array.isArray(context)?context:[context];const plans=Array.isArray(progress)?progress:[progress];const last=plans[0];if(!last||!last.next){return{context}}const lastLooperMarker=contents.findLastIndex(item=>item.role===\"$metadata\"&&item.type===\"looper\");if(lastLooperMarker>=0){const pastLooper=contents.slice(lastLooperMarker);const hasModel=pastLooper.some(item=>item.role===\"model\");if(hasModel){return{context:contents}}}contents.push({role:\"user\",parts:[{text:last.next}]});return{context:contents}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "progress": { - "type": "array", - "items": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [ - "next" - ], - "additionalProperties": false - } - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Add Looper Task", - "description": "If there is a pending Looper task, add it." - } - }, - { - "id": "runJavascript-5", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context,toAdd})=>{if(!context)throw new Error(\"Context is required\");const existing=Array.isArray(context)?context:[context];const incoming=toAdd;if(typeof incoming===\"string\"){return{context:existing}}if(!incoming.parts){const containsUserRole=existing.filter(item=>item.role!==\"model\"&&item.role!==\"$metadata\").length>0;if(!containsUserRole){return{context:[...existing,{role:\"user\",parts:[{text:\"Do your magic\"}]}]}}return{context:existing}}if(!incoming.role){incoming.role=\"user\"}const last=existing[existing.length-1];if(!last){return{context:[incoming]}}if(last.role!==incoming.role){return{context:[...existing,incoming]}}else{const result=structuredClone(existing);const index=result.length-1;result[index].parts.push(...incoming.parts);return{context:result}}};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "looper" - }, - "data": { - "type": "object", - "properties": { - "max": { - "description": "Maximum iterations to make. This can be used to create simple\n\"repeat N times\" loops.", - "type": "number" - }, - "todo": { - "description": "Plan items. Each item represents one trip down the \"Loop\" output, and\nat the end of the list, the \"Context Out\".", - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ] - } - }, - "doneMarker": { - "description": "The marker that will be used by others to signal completion of the job.", - "type": "string" - }, - "done": { - "description": "Indicator that this job is done.", - "type": "boolean" - }, - "appendLast": { - "description": "Whether to append only the last item in the loop to the context or all\nof them.", - "type": "boolean" - }, - "returnLast": { - "description": "Whether to return only last item from the context as the final product\nor all of them;", - "type": "boolean" - }, - "next": { - "description": "The next task.", - "type": "string" - } - } - } - }, - "required": [ - "data", - "type" - ] - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "split" - }, - "data": { - "type": "object", - "properties": { - "type": { - "description": "There are three types of split markers:\n- start: the beginning of the split\n- next: the separator between the split parts\n- end: the end of the split", - "enum": [ - "end", - "next", - "start" - ], - "type": "string" - }, - "id": { - "description": "Unique identifier for the split.", - "type": "string" - } - }, - "required": [ - "id", - "type" - ] - } - }, - "required": [ - "data", - "type" - ] - } - ] - } - ] - } - }, - "toAdd": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "type": "string" - } - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Add Task", - "description": "Adding task to the prompt." - } - }, - { - "id": "runJavascript-6", - "type": "runJavascript", - "configuration": { - "code": "// src/util.ts\n/**\n * @license\n * Copyright 2024 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\nfunction unique(params) {\n return Array.from(new Set(params));\n}\nfunction toId(param) {\n return `p-${param}`;\n}\nfunction isEmptyContent(content) {\n if (!content) return true;\n if (typeof content === \"string\") return true;\n if (!content.parts?.length) return true;\n if (content.parts.length > 1) return false;\n const part = content.parts[0];\n if (!(\"text\" in part)) return true;\n if (part.text.trim() === \"\") return true;\n return false;\n}\nfunction isLLMContent(nodeValue) {\n if (typeof nodeValue !== \"object\" || !nodeValue) return false;\n if (nodeValue === null || nodeValue === void 0) return false;\n if (\"role\" in nodeValue && nodeValue.role === \"$metadata\") {\n return true;\n }\n return \"parts\" in nodeValue && Array.isArray(nodeValue.parts);\n}\nfunction isLLMContentArray(nodeValue) {\n if (!Array.isArray(nodeValue)) return false;\n if (nodeValue.length === 0) return true;\n return isLLMContent(nodeValue.at(-1));\n}\nfunction toTitle(id) {\n const spaced = id?.replace(/[_-]/g, \" \");\n return (spaced?.at(0)?.toUpperCase() ?? \"\") + (spaced?.slice(1)?.toLowerCase() ?? \"\");\n}\n\n// src/js-components/substitute.ts\n/**\n * @license\n * Copyright 2024 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\nfunction run(inputParams) {\n const { in: context = [], persona, task, ...inputs } = inputParams;\n const personaParams = findParams(persona);\n const taskParams = findParams(task);\n const params = mergeParams(personaParams, taskParams);\n const values = collectValues(params, inputs);\n if (context.length === 0 && !task) {\n throw new Error(\n \"Both conversation Context and Task are empty. Specify at least one of them.\"\n );\n }\n return {\n in: context,\n persona: subContent(persona, values),\n task: subContent(task, values),\n outs: collectOuts(personaParams, taskParams)\n };\n}\nfunction collectOuts(...paramsList) {\n const functionNames = unique(\n paramsList.flat().map((param) => {\n const { name, op } = param;\n if (op !== \"out\") return null;\n return name;\n }).filter(Boolean)\n );\n return functionNames.map((name) => {\n const toolName = `TOOL_${name.toLocaleUpperCase()}`;\n return {\n name: toolName,\n description: `Call this function when asked to invoke the \"${toolName}\" tool.`\n };\n });\n}\nfunction findParams(content) {\n const parts = content?.parts;\n if (!parts) return [];\n const results = parts.flatMap((part) => {\n if (!(\"text\" in part)) return [];\n const matches = part.text.matchAll(\n /{{s*(?[w-]+)(?:s*|s*(?[w-]*)(?::s*\"(?[w-]+)\")?)?s*}}/g\n );\n return unique(Array.from(matches)).map((match) => {\n const name = match.groups?.name || \"\";\n const op = match.groups?.op || \"\";\n const arg = match.groups?.arg || \"\";\n if (!name) return null;\n return { name, op, arg, locations: [{ part, parts }] };\n }).filter(Boolean);\n });\n return results;\n}\nfunction mergeParams(...paramList) {\n const result = paramList.reduce((acc, params) => {\n for (const param of params) {\n if (param.op && param.op !== \"in\") {\n continue;\n }\n const { name, locations } = param;\n const existing = acc[name];\n if (existing) {\n existing.push(...locations);\n } else {\n acc[name] = locations;\n }\n }\n return acc;\n }, {});\n return result;\n}\nfunction subContent(content, values) {\n if (Array.isArray(content)) {\n content = content.at(-1);\n }\n if (isEmptyContent(content)) return \"\";\n return {\n role: content.role || \"user\",\n parts: mergeTextParts(\n splitToTemplateParts(content).flatMap((part) => {\n if (\"param\" in part) {\n const { op = \"in\" } = part;\n if (op === \"in\") {\n const value = values[part.param];\n if (typeof value === \"string\") {\n return { text: value };\n } else if (isLLMContent(value)) {\n return value.parts;\n } else if (isLLMContentArray(value)) {\n const last = value.at(-1);\n return last ? last.parts : [];\n } else {\n return { text: JSON.stringify(value) };\n }\n } else {\n return { text: `\"TOOL_${part.param.toLocaleUpperCase()}\"` };\n }\n } else {\n return part;\n }\n })\n )\n };\n}\nfunction mergeTextParts(parts) {\n const merged = [];\n for (const part of parts) {\n if (\"text\" in part) {\n const last = merged[merged.length - 1];\n if (last && \"text\" in last) {\n last.text += part.text;\n } else {\n merged.push(part);\n }\n } else {\n merged.push(part);\n }\n }\n return merged;\n}\nfunction splitToTemplateParts(content) {\n const parts = [];\n for (const part of content.parts) {\n if (!(\"text\" in part)) {\n parts.push(part);\n continue;\n }\n const matches = part.text.matchAll(\n /{{s*(?[w-]+)(?:s*|s*(?[w-]*)(?::s*\"(?[w-]+)\")?)?s*}}/g\n );\n let start = 0;\n for (const match of matches) {\n const name = match.groups?.name || \"\";\n const op = match.groups?.op;\n const arg = match.groups?.arg;\n const end = match.index;\n if (end > start) {\n parts.push({ text: part.text.slice(start, end) });\n }\n parts.push({ param: name, op, arg });\n start = end + match[0].length;\n }\n if (start < part.text.length) {\n parts.push({ text: part.text.slice(start) });\n }\n }\n return parts;\n}\nfunction collectValues(params, inputs) {\n const values = {};\n for (const param in params) {\n const id = toId(param);\n const value = inputs[id];\n if (!value) {\n const title = toTitle(param);\n throw new Error(`Missing required parameter: ${title}`);\n }\n values[param] = value;\n }\n return values;\n}\nexport {\n run\n};\n", - "inputSchema": { - "type": "object", - "properties": { - "in": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "looper" - }, - "data": { - "type": "object", - "properties": { - "max": { - "description": "Maximum iterations to make. This can be used to create simple\n\"repeat N times\" loops.", - "type": "number" - }, - "todo": { - "description": "Plan items. Each item represents one trip down the \"Loop\" output, and\nat the end of the list, the \"Context Out\".", - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ] - } - }, - "doneMarker": { - "description": "The marker that will be used by others to signal completion of the job.", - "type": "string" - }, - "done": { - "description": "Indicator that this job is done.", - "type": "boolean" - }, - "appendLast": { - "description": "Whether to append only the last item in the loop to the context or all\nof them.", - "type": "boolean" - }, - "returnLast": { - "description": "Whether to return only last item from the context as the final product\nor all of them;", - "type": "boolean" - }, - "next": { - "description": "The next task.", - "type": "string" - } - } - } - }, - "required": [ - "data", - "type" - ] - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "split" - }, - "data": { - "type": "object", - "properties": { - "type": { - "description": "There are three types of split markers:\n- start: the beginning of the split\n- next: the separator between the split parts\n- end: the end of the split", - "enum": [ - "end", - "next", - "start" - ], - "type": "string" - }, - "id": { - "description": "Unique identifier for the split.", - "type": "string" - } - }, - "required": [ - "id", - "type" - ] - } - }, - "required": [ - "data", - "type" - ] - } - ] - } - ] - } - }, - "persona": { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - "task": { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "in": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "looper" - }, - "data": { - "type": "object", - "properties": { - "max": { - "description": "Maximum iterations to make. This can be used to create simple\n\"repeat N times\" loops.", - "type": "number" - }, - "todo": { - "description": "Plan items. Each item represents one trip down the \"Loop\" output, and\nat the end of the list, the \"Context Out\".", - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ] - } - }, - "doneMarker": { - "description": "The marker that will be used by others to signal completion of the job.", - "type": "string" - }, - "done": { - "description": "Indicator that this job is done.", - "type": "boolean" - }, - "appendLast": { - "description": "Whether to append only the last item in the loop to the context or all\nof them.", - "type": "boolean" - }, - "returnLast": { - "description": "Whether to return only last item from the context as the final product\nor all of them;", - "type": "boolean" - }, - "next": { - "description": "The next task.", - "type": "string" - } - } - } - }, - "required": [ - "data", - "type" - ] - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "split" - }, - "data": { - "type": "object", - "properties": { - "type": { - "description": "There are three types of split markers:\n- start: the beginning of the split\n- next: the separator between the split parts\n- end: the end of the split", - "enum": [ - "end", - "next", - "start" - ], - "type": "string" - }, - "id": { - "description": "Unique identifier for the split.", - "type": "string" - } - }, - "required": [ - "id", - "type" - ] - } - }, - "required": [ - "data", - "type" - ] - } - ] - } - ] - } - }, - "persona": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "type": "string" - } - ] - }, - "task": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "type": "string" - } - ] - }, - "outs": { - "type": "array", - "items": { - "$ref": "#/definitions/def-11" - } - } - }, - "required": [ - "in", - "outs", - "persona", - "task" - ], - "definitions": { - "def-11": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "parameters": { - "$ref": "#/definitions/def-14" - } - }, - "required": [ - "name" - ] - }, - "def-14": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "type": { - "anyOf": [ - { - "type": "array", - "items": { - "type": "string" - } - }, - { - "type": "string" - } - ] - }, - "properties": { - "type": "object" - }, - "required": { - "type": "array", - "items": { - "type": "string" - } - }, - "format": { - "type": "string" - }, - "behavior": { - "description": "Can be used to provide additional hints to the UI or to other parts of\nthe system about behavior of this particular input/output or input/output\nport.", - "type": "array", - "items": { - "enum": [ - "board", - "bubble", - "code", - "config", - "deprecated", - "error", - "google-drive-file-id", - "google-drive-query", - "image", - "json-schema", - "llm-content", - "ports-spec", - "stream", - "transient" - ], - "type": "string" - } - }, - "transient": { - "type": "boolean" - }, - "enum": { - "type": "array", - "items": { - "type": "string" - } - }, - "default": { - "description": "The default value of the schema. The UI can use this to pre-populate a\nfield with a value, if there is no `examples` present.", - "type": "string" - }, - "additionalProperties": { - "anyOf": [ - { - "$ref": "#/definitions/def-14" - }, - { - "type": "boolean" - } - ] - }, - "items": { - "anyOf": [ - { - "$ref": "#/definitions/def-14" - }, - { - "type": "array", - "items": { - "$ref": "#/definitions/def-14" - } - } - ] - }, - "minItems": { - "type": "number" - }, - "examples": { - "description": "Can be used by UI to pre-populate a field with a value that could be\nused as an example.", - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Substitute Parameters", - "description": "Performing parameter substitution, if needed." - } - }, - { - "id": "runJavascript-7", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context,forkOutputs})=>{const fork=forkOutputs;const existing=Array.isArray(context)?context:[context];const progress=[];for(let i=existing.length-1;i>=0;i--){const item=existing[i];if(item.role===\"$metadata\"&&item.type===\"looper\"){progress.push(item.data)}}if(fork){if(progress.length){return{progress}}else{return{context}}}else{return{context,progress}}};", - "forkOutputs": false, - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ] - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object" - } - }, - "required": [ - "args", - "name" - ] - } - }, - "required": [ - "functionCall" - ] - } - ] - } - }, - "role": { - "enum": [ - "model", - "tool", - "user" - ], - "type": "string" - } - }, - "required": [ - "parts" - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "looper" - }, - "data": { - "type": "object", - "properties": { - "max": { - "description": "Maximum iterations to make. This can be used to create simple\n\"repeat N times\" loops.", - "type": "number" - }, - "todo": { - "description": "Plan items. Each item represents one trip down the \"Loop\" output, and\nat the end of the list, the \"Context Out\".", - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ] - } - }, - "doneMarker": { - "description": "The marker that will be used by others to signal completion of the job.", - "type": "string" - }, - "done": { - "description": "Indicator that this job is done.", - "type": "boolean" - }, - "appendLast": { - "description": "Whether to append only the last item in the loop to the context or all\nof them.", - "type": "boolean" - }, - "returnLast": { - "description": "Whether to return only last item from the context as the final product\nor all of them;", - "type": "boolean" - }, - "next": { - "description": "The next task.", - "type": "string" - } - } - } - }, - "required": [ - "data", - "type" - ] - } - ] - }, - { - "allOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "const": "$metadata" - } - }, - "required": [ - "role" - ] - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "split" - }, - "data": { - "type": "object", - "properties": { - "type": { - "description": "There are three types of split markers:\n- start: the beginning of the split\n- next: the separator between the split parts\n- end: the end of the split", - "enum": [ - "end", - "next", - "start" - ], - "type": "string" - }, - "id": { - "description": "Unique identifier for the split.", - "type": "string" - } - }, - "required": [ - "id", - "type" - ] - } - }, - "required": [ - "data", - "type" - ] - } - ] - } - ] - } - }, - "forkOutputs": { - "type": "boolean" - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "progress": { - "type": "array", - "items": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [ - "next" - ], - "additionalProperties": false - } - }, - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - }, - "raw": true - }, - "metadata": { - "title": "Read Progress so far" - } - }, - { - "id": "runJavascript-8", - "type": "runJavascript", - "configuration": { - "code": "const run = ({context,generated})=>{if(!context)throw new Error(\"Context is required\");if(!generated)throw new Error(\"Generated is required\");const c=context;const g=generated;let doneMarker=null;for(let i=0;i{const b=board;const inputs=b.nodes.filter(node=>node.type===\"input\")||[];const outputs=b.nodes.filter(node=>node.type===\"output\");if(outputs.length===0){throw new Error(\"No outputs found\")}const inputSchema=inputs[0]?.configuration?.schema||{};const outputSchema=outputs[0].configuration?.schema;if(!outputSchema){throw new Error(\"No output schema found\")}const properties={};const flags={};for(const key in inputSchema.properties){const property=inputSchema.properties[key];const isObject=property.type===\"object\";const isArray=property.type===\"array\";const type=isObject||isArray?\"string\":property.type;if(isObject&&property.behavior?.includes(\"llm-content\")){flags.inputLLMContent=key}else if(isArray&&property.items?.behavior?.includes(\"llm-content\")){flags.inputLLMContentArray=key;continue}const description2=property.description||property.title||\"text\";properties[key]={type,description:description2}}if(flags.inputLLMContentArray){if(flags.inputLLMContentArray!==\"context\"){const c=b.args?.context;if(c){b.args??={};b.args[flags.inputLLMContentArray]=c;delete b.args.context}}}else{delete b.args?.context}for(const key in outputSchema.properties){const property=outputSchema.properties[key];const isObject=property.type===\"object\";const isArray=property.type===\"array\";if(isObject&&property.behavior?.includes(\"llm-content\")){flags.outputLLMContent=key}else if(isArray&&property.items?.behavior?.includes(\"llm-content\")){flags.outputLLMContentArray=key}}const name=b.title?.replace(/\\W/g,\"_\")||\"function\";const description=b.description;const parameters=Object.entries(properties).length>0?{type:\"object\",properties}:void 0;const f={name,description};if(parameters){f.parameters=parameters}return{function:f,returns:outputSchema,flags,board}};", - "inputSchema": { - "type": "object", - "properties": { - "board": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "function": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "parameters": { - "type": "object", - "behavior": [ - "json-schema" - ], - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "required": [ - "name" - ], - "additionalProperties": false - }, - "board": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true, - "behavior": [ - "board" - ] - }, - "flags": { - "type": "object", - "properties": { - "inputLLMContent": { - "type": "string" - }, - "inputLLMContentArray": { - "type": "string" - }, - "outputLLMContent": { - "type": "string" - }, - "outputLLMContentArray": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - } - }, - "raw": true - }, - "metadata": { - "title": "Get Function Signature from board" - } - } - ] - }, - "subgraph-1": { - "title": "Invoke Board With Args", - "description": "Takes one item of `boardInvocationAssembler` output and invokes it as a board with arguments.", - "version": "0.0.1", - "edges": [ - { - "from": "input-0", - "to": "runJavascript-2", - "out": "item", - "in": "item" - }, - { - "from": "input-0", - "to": "runJavascript-3", - "out": "item", - "in": "item" - }, - { - "from": "invoke-0", - "to": "runJavascript-1", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "item", - "in": "item" - }, - { - "from": "runJavascript-1", - "to": "runJavascript-0", - "out": "result", - "in": "result" - }, - { - "from": "runJavascript-2", - "to": "invoke-0", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-3", - "to": "runJavascript-0", - "out": "flags", - "in": "flags" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": "object", - "properties": { - "$flags": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "$flags" - ], - "additionalProperties": true - } - }, - "required": [ - "item" - ] - } - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "item" - ] - } - } - }, - { - "id": "invoke-0", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke board", - "description": "Invoking the board with unpacked arguments" - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = ({result,flags})=>{let contentDetected=false;const inputs=result;const item=[];const f=flags;if(f){if(f.outputLLMContent){const content=inputs[f.outputLLMContent];content.role=\"tool\";item.push(content);contentDetected=true}else if(f.outputLLMContentArray){const contentArray=inputs[f.outputLLMContentArray];contentArray.forEach(content=>{if(content.role!==\"$metadata\"){content.role=\"tool\"}item.push(content)});contentDetected=true}}else{for(const key in inputs){const input=inputs[key];if(input!==null&&typeof input===\"object\"&&\"content\"in input){const content=input.content;if(content.parts&&Array.isArray(content.parts)){content.role=\"tool\";item.push(content);contentDetected=true}}}}if(!contentDetected){const text=JSON.stringify(inputs);item.push({parts:[{text}],role:\"tool\"})}return{item}};", - "inputSchema": { - "type": "object", - "properties": { - "result": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - }, - "flags": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "item": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "raw": true - }, - "metadata": { - "title": "Format results", - "description": "Formatting results" - } - }, - { - "id": "runJavascript-1", - "type": "runJavascript", - "configuration": { - "code": "const run = result=>({result});", - "inputSchema": { - "type": "object", - "properties": { - "": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "result": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "raw": true - }, - "metadata": { - "title": "Pack results", - "description": "Packing results" - } - }, - { - "id": "runJavascript-2", - "type": "runJavascript", - "configuration": { - "code": "const run = ({item:item2})=>{const{$flags,...result}=item2;return result};", - "inputSchema": { - "type": "object", - "properties": { - "item": { - "type": "object", - "properties": { - "$flags": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "$flags" - ], - "additionalProperties": true - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": {} - }, - "raw": true - }, - "metadata": { - "title": "Unpack args", - "description": "Unpacking board arguments" - } - }, - { - "id": "runJavascript-3", - "type": "runJavascript", - "configuration": { - "code": "const run = ({item:item2})=>{const{$flags}=item2;return{flags:$flags}};", - "inputSchema": { - "type": "object", - "properties": { - "item": { - "type": "object", - "properties": { - "$flags": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "$flags" - ], - "additionalProperties": true - } - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "flags": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "raw": true - }, - "metadata": { - "title": "Get flags", - "description": "Getting flags for the board invocation" - } - } - ] - }, - "subgraph-2": { - "title": "Specialist Describer", - "description": "A custom describer for the Specialist component", - "version": "0.1.0", - "edges": [ - { - "from": "input-0", - "to": "runJavascript-0", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "inputSchema", - "in": "inputSchema" - }, - { - "from": "runJavascript-0", - "to": "output-0", - "out": "outputSchema", - "in": "outputSchema" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "inputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - }, - "outputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "required": [ - "inputSchema", - "outputSchema" - ] - } - } - }, - { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "code": "const run = function describeSpecialist(inputs){const{$inputSchema,$outputSchema,persona,task}=inputs;const inputSchema={type:\"object\",additionalProperties:false,properties:{...$inputSchema.properties,in:{title:\"Context in\",description:\"Incoming conversation context\",type:\"array\",items:{type:\"object\",behavior:[\"llm-content\"]},examples:[]},task:{title:\"Task\",description:\"(Optional) Provide a specific task with clear instructions for the worker to complete using the conversation context. Use mustache-style {{params}} to add parameters.\",type:\"object\",default:'{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}',behavior:[\"llm-content\",\"config\"],examples:[]},persona:{type:\"object\",behavior:[\"llm-content\",\"config\"],title:\"Persona\",description:\"Describe the worker's skills, capabilities, mindset, and thinking process. Use mustache-style {{params}} to add parameters.\",default:'{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}',examples:[]}},required:[]};const all=[...collectParams(textFromLLMContent(persona)),...collectParams(textFromLLMContent(task))];const params=[];const outs=[];for(const param of all){const{op=\"in\"}=param;if(op===\"in\"){params.push(param.name)}else{outs.push(param.name)}}const inputProps=Object.fromEntries(unique(params).map(param=>[toId(param),{title:toTitle(param),description:`The value to substitute for the parameter \"${param}\"`,type:\"string\"}]));const outputProps=Object.fromEntries(unique(outs).map(param=>[toId(`TOOL_${param.toLocaleUpperCase()}`),{title:toTitle(param),description:`The output chosen when the \"${param}\" tool is invoked`,type:\"string\"}]));const required=params.map(toId);return mergeSchemas(inputSchema,$outputSchema,inputProps,outputProps);function mergeSchemas(inputSchema2,outputSchema,properties,outputProps2){return{inputSchema:{...inputSchema2,properties:{...inputSchema2.properties,...properties},required:[...inputSchema2.required||[],...required]},outputSchema:{...outputSchema,properties:{...outputSchema.properties,...outputProps2}}}}__name(mergeSchemas,\"mergeSchemas\");function toId(param){return`p-${param}`}__name(toId,\"toId\");function toTitle(id){const spaced=id?.replace(/[_-]/g,\" \");return(spaced?.at(0)?.toUpperCase()??\"\")+(spaced?.slice(1)?.toLowerCase()??\"\")}__name(toTitle,\"toTitle\");function textFromLLMContent(content2){return content2?.parts.map(item=>{return\"text\"in item?item.text:\"\"}).join(\"\\n\")||\"\"}__name(textFromLLMContent,\"textFromLLMContent\");function unique(params2){return Array.from(new Set(params2))}__name(unique,\"unique\");function collectParams(text){if(!text)return[];const matches=text.matchAll(/{{\\s*(?[\\w-]+)(?:\\s*\\|\\s*(?[\\w-]*)(?::\\s*\"(?[\\w-]+)\")?)?\\s*}}/g);return Array.from(matches).map(match=>{const name=match.groups?.name||\"\";const op=match.groups?.op;const arg=match.groups?.arg;return{name,op,arg,locations:[]}})}__name(collectParams,\"collectParams\")};", - "inputSchema": { - "type": "object", - "properties": {}, - "additionalProperties": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - }, - "name": "run", - "outputSchema": { - "type": "object", - "properties": { - "inputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - }, - "outputSchema": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - }, - "raw": true - }, - "metadata": { - "title": "Describe", - "description": "Describes the Specialist" - } - } - ] - } - } -} \ No newline at end of file diff --git a/packages/agent-kit/package.json b/packages/agent-kit/package.json deleted file mode 100644 index 16260a1a79f..00000000000 --- a/packages/agent-kit/package.json +++ /dev/null @@ -1,171 +0,0 @@ -{ - "name": "@google-labs/agent-kit", - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "version": "0.12.0", - "description": "A Breadboard Kit for building agent-like experiences", - "main": "./dist/src/index.js", - "exports": { - ".": "./dist/src/index.js", - "./agent.kit.json": "./agent.kit.json" - }, - "types": "dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "test": "wireit", - "build": "wireit", - "build:tsc": "wireit", - "lint": "wireit", - "generate-kit-manifest": "wireit", - "generate:js-components": "wireit", - "generate:graphs": "wireit" - }, - "wireit": { - "generate-kit-manifest": { - "command": "tsx src/generate-kit-manifest.ts", - "dependencies": [ - "build:tsc" - ], - "files": [ - "src/generate-kit-manifest.ts" - ], - "output": [ - "agent.kit.json" - ] - }, - "build": { - "dependencies": [ - "../breadboard:build", - "../core-kit:build", - "../json-kit:build", - "../template-kit:build", - "../gemini-kit:build", - "build:tsc", - "generate-kit-manifest" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "../breadboard:build:tsc", - "../core-kit:build:tsc", - "../json-kit:build:tsc", - "../template-kit:build:tsc", - "../gemini-kit:build:tsc", - "generate:js-components" - ], - "files": [ - "src/**/*.ts", - "!src/samples/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/", - "!dist/**/*.min.js{,.map}" - ], - "clean": "if-file-deleted" - }, - "generate:js-components": { - "command": "build-code --tsconfig=tsconfig.json --out=src/generated/ src/js-components/*.ts", - "files": [ - "src/**/*.ts", - "!src/generated/" - ], - "output": [ - "src/generated/" - ], - "dependencies": [ - "../build-code:build" - ] - }, - "test": { - "command": "node --test --enable-source-maps --test-reporter spec dist/tests/*.js", - "dependencies": [ - "build:tsc" - ], - "files": [ - "dist/tests/*.js", - "tests/boards/*.json" - ], - "output": [] - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - }, - "generate:graphs": { - "command": "mkdir graphs && ls dist/src/boards/*.js | xargs -n1 -r -I{} ../breadboard-cli/dist/src/index.js make \"$PWD/{}\" -o \"$PWD/graphs/\" --format", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [ - "graphs/" - ] - } - }, - "repository": { - "directory": "packages/agent-kit", - "type": "git", - "url": "https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src", - "agent.kit.json" - ], - "ava": { - "timeout": "30s", - "files": [ - "tests/**/*.ts" - ], - "workerThreads": false, - "typescript": { - "rewritePaths": { - "./": "dist/" - }, - "compile": false - } - }, - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/gemini-kit": "^0.8.0", - "@google-labs/json-kit": "^0.3.8", - "@google-labs/template-kit": "^0.3.10", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "tsx": "^4.19.1", - "typescript": "^5.6.2" - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0" - } -} diff --git a/packages/agent-kit/src/boards/content.ts b/packages/agent-kit/src/boards/content.ts deleted file mode 100644 index 0ad0ee23f86..00000000000 --- a/packages/agent-kit/src/boards/content.ts +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { starInputs, board, object, array } from "@breadboard-ai/build"; -import { content } from "../templating.js"; -import { code } from "@google-labs/core-kit"; -import contentDescriber from "./internal/content-describer.js"; -import { GenericBoardDefinition } from "@breadboard-ai/build/internal/board/board.js"; -import { llmContentType } from "../context.js"; - -const inputs = starInputs({ type: object({}, "unknown") }); - -const substituteParams = code( - { - $metadata: { - title: "Substitute Parameters", - description: "Performing parameter substitution, if needed.", - }, - "*": inputs, - }, - { - context: array(llmContentType), - }, - content -); - -export default board({ - title: "Content", - description: - "Use it as a way to initialize or add to conversation context, optionally applying extra arguments with mustache-style {{placeholders}}.", - version: "0.1.0", - metadata: { - icon: "code-blocks", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#content", - }, - }, - inputs: { - "*": inputs, - }, - outputs: { - context: substituteParams.outputs.context, - }, - describer: contentDescriber as GenericBoardDefinition, -}); diff --git a/packages/agent-kit/src/boards/human.ts b/packages/agent-kit/src/boards/human.ts deleted file mode 100644 index 4b0e7a7b912..00000000000 --- a/packages/agent-kit/src/boards/human.ts +++ /dev/null @@ -1,394 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - annotate, - array, - board, - input, - jsonSchema, - output, - outputNode, - rawInput, - type Value, -} from "@breadboard-ai/build"; -import { type Schema } from "@google-labs/breadboard"; -import { code } from "@google-labs/core-kit"; -import { - addUserParts, - type Context, - contextType, - type LlmContent, -} from "../context.js"; - -export type HumanMode = "input" | "inputOutput" | "choose" | "chooseReject"; - -const context = input({ - title: "Context in", - description: "Incoming conversation context", - type: array(contextType), - default: [], -}); - -const title = input({ - title: "Title", - description: "The user label", - type: annotate("string", { behavior: ["config"] }), - default: "User", -}); - -const description = input({ - title: "Description", - description: "The user's input", - type: annotate("string", { behavior: ["config"] }), - default: "A request or response", -}); - -const areWeDoneChecker = code( - { - $id: "areWeDoneChecker", - $metadata: { - title: "Done Check", - description: "Checking to see if we can skip work altogether", - }, - context, - }, - { context: array(contextType), done: array(contextType) }, - ({ context }) => { - if (!context) throw new Error("Context is required"); - // are there any done:true in the context? - let done = false; - for (let i = 0; i < context.length; ++i) { - const item = context[i]; - if (item.role === "$metadata" && item.type === "looper") { - const plan = item.data; - if (plan.done) { - done = true; - break; - } - } - } - // TODO(aomarks) Casts required until code() supports polymorphism better. - type TempUnsafeResult = { done: Context[]; context: Context[] }; - if (done) { - return { done: context } as TempUnsafeResult; - } else { - return { context } as TempUnsafeResult; - } - } -); - -const doneOutput = outputNode( - { context: output(areWeDoneChecker.outputs.done, { title: "Context out" }) }, - { - id: "doneOutput", - title: "Done", - description: "Skipping because we're done", - } -); - -/** - * Four modes: - * - "input" -- there is no pending model output to show, so we just - * show the user input. - * - "inputOutput" -- there is a model output to show, so we show it - * first, then ask for user input. - * - "choose" -- the context contains split output metadata, so we - * show the model output, and a choice-picker for the user and optionally, a - * text box for the user to provide feedback. - * - "chooseReject" -- the context contains a split output - * metadata, so we show the model output, and a choice-picker for the user - * with an option to reject and try again, and optionally, a text box for the - * user to provide feedback. - * - * Strategies for each mode, a different output: - * - "input" -- just the context. - * - "inputOutput" -- just the context. - * - "choose" -- the context and the `ChoicePicker` data structure. - */ -export const routeByMode = code( - { - $id: "routeByMode", - $metadata: { - title: "Compute Mode", - description: "Determining the mode of operation", - }, - context: areWeDoneChecker.outputs.context, - }, - { - input: array(contextType), - output: array(contextType), - choose: array(contextType), - }, - ({ context }) => { - // TODO(aomarks) Casts required until code() supports polymorphism better. - type TempUnsafeResult = { - input: Context[]; - output: Context[]; - choose: Context[]; - }; - if (!context) { - return { input: [] } as object as TempUnsafeResult; - } - const c = asContextArray(context); - const mode = computeMode(c); - if (mode === "input") { - return { input: c } as TempUnsafeResult; - } else if (mode === "inputOutput") { - return { input: c, output: c } as TempUnsafeResult; - } - return { output: onlyChoices(c), choose: c } as TempUnsafeResult; - - function asContextArray(context: unknown): Context[] { - const input = context as Context | Context[]; - return Array.isArray(input) ? input : [input]; - } - - function onlyChoices(context: Context[]): Context[] { - const choices: Context[] = []; - const reversed = [...context].reverse(); - for (const item of reversed) { - choices.push(item); - if ( - item.role === "$metadata" && - item.type === "split" && - item.data.type === "start" - ) { - break; - } - } - return choices.reverse(); - } - - function computeMode(context: Context[]): HumanMode { - const lastItem = context[context.length - 1]; - if (!lastItem) { - return "input"; - } - if (lastItem.role === "user") { - return "input"; - } - if (lastItem.role !== "$metadata") { - return "inputOutput"; - } - if (lastItem.type === "split" && lastItem.data.type === "end") { - const splitId = lastItem.data.id; - let choiceCounter = 1; - for (let i = context.length - 2; i >= 0; i--) { - const item = context[i]; - if (item.role === "$metadata" && item.type === "split") { - const { id, type } = item.data; - if (splitId !== id) { - return "inputOutput"; - } - if (type === "start") { - break; - } - choiceCounter++; - } - } - if (choiceCounter > 1) { - return "choose"; - } - } - return "inputOutput"; - } - } -); - -const createSchema = code( - { - $id: "createSchema", - $metadata: { - title: "Create Schema", - description: "Creating a schema for user input", - }, - title, - description, - context: routeByMode.outputs.input, - }, - { schema: jsonSchema }, - ({ title, description }) => { - const text: Schema = { - title, - description, - type: "object", - behavior: ["transient", "llm-content"], - examples: [JSON.stringify({ parts: [{ text: "" }] })], - }; - const schema: Schema = { - type: "object", - properties: { text }, - }; - return { schema }; - } -); - -export const buildChooseSchema = code( - { - $id: "buildChooseSchema", - $metadata: { - title: "Choose Options", - description: "Creating the options to choose from", - }, - title, - description, - context: routeByMode.outputs.choose, - }, - { total: "number", schema: jsonSchema }, - ({ context, title, description }) => { - const c = asContextArray(context).reverse(); - const choices = []; - for (const item of c) { - if (item.role === "$metadata" && item.type === "split") { - const type = item.data.type; - if (type === "start") { - break; - } else { - choices.push(`Choice ${choices.length + 1}`); - } - } - } - const schema: Schema = { - type: "object", - properties: { - choice: { - title, - description, - type: "string", - enum: choices, - }, - }, - }; - return { schema, total: choices.length }; - - function asContextArray(context: Context | Context[]): Context[] { - return Array.isArray(context) ? context : [context]; - } - } -); - -const chooseInput = rawInput({ - $id: "chooseInput", - $metadata: { - title: "Look at the choices above and pick one", - description: "Asking user to choose an option", - }, - schema: buildChooseSchema.outputs.schema, -}); - -export const pickChoice = code( - { - $id: "pickChoice", - $metadata: { - title: "Read Choice", - description: "Reading the user's choice", - }, - context: routeByMode.outputs.choose, - choice: chooseInput.unsafeOutput("choice") as Value, - total: buildChooseSchema.outputs.total, - }, - { context: array(contextType) }, - ({ context, choice, total }) => { - const chosenIndex = total - parseInt(choice.split(" ")[1], 10); - const c = context.reverse(); - const current: Context[] = []; - let found: "before" | "found" | "after" = "before"; - let chunkIndex = 0; - let startIndex = 0; - for (const [i, item] of c.entries()) { - if (item.role === "$metadata" && item.type === "split") { - const type = item.data.type; - if (type === "start") { - startIndex = i; - break; - } else { - if (chunkIndex === chosenIndex) { - found = "found"; - } else if (chunkIndex > chosenIndex) { - found = "after"; - } else { - found = "before"; - } - chunkIndex++; - } - } else if (found === "found") { - current.push(item); - } - } - const preamble = c.slice(startIndex + 1).reverse(); - if (!found) { - throw new Error(`Integrity error: choice "${choice}" not found`); - } - return { context: [...preamble, ...current.reverse()] }; - } -); - -const choiceOutput = outputNode( - { context: output(pickChoice.outputs.context, { title: "Context out" }) }, - { - id: "choiceOutput", - title: "Choice Output", - description: "Outputting the user's choice", - } -); - -const displayOutput = outputNode( - { - output: output(routeByMode.outputs.output, { - title: "Output", - description: "The output to display", - }), - }, - { - id: "output", - title: "Output", - description: "Displaying the output to the user.", - bubble: true, - } -); - -const userInput = rawInput({ - $id: "input", - $metadata: { title: "Input", description: "Asking user for input" }, - schema: createSchema.outputs.schema, -}); - -const appendContext = code( - { - $id: "appendContext", - $metadata: { - title: "Append Context", - description: "Appending user input to the conversation context", - }, - context: routeByMode.outputs.input, - toAdd: userInput.unsafeOutput("text") as Value, - }, - { context: array(contextType) }, - addUserParts -); - -const contextOutput = outputNode({ - context: output(appendContext.outputs.context, { title: "Context out" }), - text: output(userInput.unsafeOutput("text") as Value, { - deprecated: true, - }), -}); - -export default board({ - title: "Human", - metadata: { - icon: "human", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#human", - }, - }, - description: - "A human in the loop. Use this node to insert a real person (user input) into your team of synthetic workers.", - version: "0.0.1", - inputs: { context, title, description }, - outputs: [doneOutput, displayOutput, contextOutput, choiceOutput], -}); diff --git a/packages/agent-kit/src/boards/internal/board-to-function.ts b/packages/agent-kit/src/boards/internal/board-to-function.ts deleted file mode 100644 index d79cae60583..00000000000 --- a/packages/agent-kit/src/boards/internal/board-to-function.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { annotate, board, input, object } from "@breadboard-ai/build"; -import { code, coreKit } from "@google-labs/core-kit"; -import { llmContentType } from "../../context.js"; -import { - functionCallFlagsType, - functionDeclarationType, - functionSignatureFromBoardFunction, -} from "../../function-calling.js"; - -const item = input(); -const context = input({ type: llmContentType }); - -const importBoard = coreKit.curry({ - $board: item, - context, -}); - -const getFunctionSignature = code( - { - $metadata: { title: "Get Function Signature from board" }, - board: importBoard.outputs.board, - }, - { - function: functionDeclarationType, - board: annotate(object({}, "unknown"), { behavior: ["board"] }), - flags: functionCallFlagsType, - }, - functionSignatureFromBoardFunction -); - -export default board({ - title: "Board to functions", - description: - "Use this board to convert specified boards into function-calling signatures", - inputs: { item, context }, - outputs: { - function: getFunctionSignature.outputs.function, - boardURL: getFunctionSignature.outputs.board, - flags: getFunctionSignature.outputs.flags, - }, -}); diff --git a/packages/agent-kit/src/boards/internal/content-describer.ts b/packages/agent-kit/src/boards/internal/content-describer.ts deleted file mode 100644 index 62542a88458..00000000000 --- a/packages/agent-kit/src/boards/internal/content-describer.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { board, object, starInputs } from "@breadboard-ai/build"; -import { code } from "@google-labs/core-kit"; -import { describeContent } from "../../templating.js"; - -// A board that acts as a custom describer for the -// Content component. - -const inputs = starInputs({ type: object({}, "unknown") }); - -const describe = code( - { - $metadata: { - title: "Describe", - description: "Describes the content", - }, - "*": inputs, - }, - { inputSchema: object({}, "unknown"), outputSchema: object({}, "unknown") }, - describeContent -); - -export default board({ - title: "Content Describer", - description: "A custom describer for the Content component", - version: "0.1.0", - inputs: { "*": inputs }, - outputs: { - inputSchema: describe.outputs.inputSchema, - outputSchema: describe.outputs.outputSchema, - }, -}); diff --git a/packages/agent-kit/src/boards/internal/invoke-board-with-args.ts b/packages/agent-kit/src/boards/internal/invoke-board-with-args.ts deleted file mode 100644 index a92101911d5..00000000000 --- a/packages/agent-kit/src/boards/internal/invoke-board-with-args.ts +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { board, input, object } from "@breadboard-ai/build"; -import { - type ConvertBreadboardType, - type JsonSerializable, -} from "@breadboard-ai/build/internal/type-system/type.js"; -import { code, coreKit } from "@google-labs/core-kit"; -import { resultFormatterFunction } from "../../function-calling.js"; - -const itemType = object({ $flags: "unknown" }, "unknown"); -type Item = ConvertBreadboardType; -type Flags = JsonSerializable; - -const item = input({ type: itemType }); - -const unpackArgs = code( - { - $metadata: { - title: "Unpack args", - description: "Unpacking board arguments", - }, - item, - }, - {}, - ({ item }: { item: Item }): Record => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { $flags, ...result } = item; - return result; - } -); - -const getFlags = code( - { - $metadata: { - title: "Get flags", - description: "Getting flags for the board invocation", - }, - item, - }, - { flags: "unknown" }, - ({ item }: { item: Item }): { flags: Flags } => { - const { $flags } = item; - return { flags: $flags }; - } -); - -const invoker = coreKit.invoke({ - $metadata: { - title: "Invoke board", - description: "Invoking the board with unpacked arguments", - }, - // TODO(aomarks) A nicer way to do star wiring. Also, why does the input port have - // to be "" instead of "*" (it doesn't work with "*"). - "": unpackArgs.unsafeOutput("*"), -}); - -const packResults = code( - { - $metadata: { title: "Pack results", description: "Packing results" }, - // TODO(aomarks) A nicer way to do star wiring. Also, why does the input port have - // to be "" instead of "*" (it doesn't work with "*"). - "": invoker.unsafeOutput("*"), - }, - { result: "unknown" }, - (result) => ({ result }) -); - -const formatResults = code( - { - $metadata: { title: "Format results", description: "Formatting results" }, - result: packResults.outputs.result, - flags: getFlags.outputs.flags, - }, - { - item: "unknown", - }, - resultFormatterFunction -); - -export default board({ - title: "Invoke Board With Args", - description: - "Takes one item of `boardInvocationAssembler` output and invokes it as a board with arguments.", - version: "0.0.1", - inputs: { item }, - outputs: { item: formatResults.outputs.item }, -}); diff --git a/packages/agent-kit/src/boards/internal/specialist-describer.ts b/packages/agent-kit/src/boards/internal/specialist-describer.ts deleted file mode 100644 index 27f6ae1ae70..00000000000 --- a/packages/agent-kit/src/boards/internal/specialist-describer.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { board, object, starInputs } from "@breadboard-ai/build"; -import { code } from "@google-labs/core-kit"; -import { describeSpecialist } from "../../templating.js"; - -const inputs = starInputs({ type: object({}, "unknown") }); - -const describe = code( - { - $metadata: { - title: "Describe", - description: "Describes the Specialist", - }, - "*": inputs, - }, - { inputSchema: object({}, "unknown"), outputSchema: object({}, "unknown") }, - describeSpecialist -); - -export default board({ - title: "Specialist Describer", - description: "A custom describer for the Specialist component", - version: "0.1.0", - inputs: { "*": inputs }, - outputs: { - inputSchema: describe.outputs.inputSchema, - outputSchema: describe.outputs.outputSchema, - }, -}); diff --git a/packages/agent-kit/src/boards/joiner.ts b/packages/agent-kit/src/boards/joiner.ts deleted file mode 100644 index 2028c751782..00000000000 --- a/packages/agent-kit/src/boards/joiner.ts +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - annotate, - array, - board, - input, - output, - starInputs, -} from "@breadboard-ai/build"; -import { code } from "@google-labs/core-kit"; -import { combineContextsFunction, contextType } from "../context.js"; - -const merge = input({ - title: "Merge Contexts", - description: "Merge the last items of all incoming conversation into one.", - type: annotate("boolean", { behavior: ["config"] }), - default: false, -}); - -const contexts = starInputs({ type: contextType }); - -const merged = code( - { merge, "*": contexts }, - { context: array(contextType) }, - combineContextsFunction -); - -const context = output(merged.outputs.context, { title: "Context out" }); - -export default board({ - title: "Joiner", - description: - "Joins two or more worker contexts into one. Great for combining results of multiple workers.", - version: "0.0.1", - metadata: { - icon: "merge-type", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#joiner", - }, - }, - inputs: { merge, "*": contexts }, - outputs: { context }, -}); diff --git a/packages/agent-kit/src/boards/looper.ts b/packages/agent-kit/src/boards/looper.ts deleted file mode 100644 index 47b79f7c285..00000000000 --- a/packages/agent-kit/src/boards/looper.ts +++ /dev/null @@ -1,364 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - annotate, - array, - board, - converge, - enumeration, - input, - inputNode, - output, - outputNode, - type Value, -} from "@breadboard-ai/build"; -import { code } from "@google-labs/core-kit"; -import gemini from "@google-labs/gemini-kit"; -import { jsonKit } from "@google-labs/json-kit"; -import { - addUserParts, - type Context, - contextType, - llmContentType, - LooperPlan, - looperPlanType, - readProgress, -} from "../context.js"; -import { Schema } from "@google-labs/breadboard"; -import { JsonSerializable } from "@breadboard-ai/build/internal/type-system/type.js"; - -const context = input({ - title: "Context in", - type: array(contextType), - description: "Incoming conversation context", - default: [], -}); - -const task = input({ - title: "Task", - type: annotate(llmContentType, { behavior: ["config"] }), - description: "The task to be used for loop planning", - default: { parts: [] }, -}); - -const model = input({ - title: "Model", - description: "Choose the model to use for this looper.", - type: annotate( - enumeration( - "gemini-1.5-flash-latest", - "gemini-1.5-pro-latest", - "gemini-1.5-pro-exp-0801", - "gemini-1.5-pro-exp-0827", - "gemini-1.5-flash-8b-exp-0827", - "gemini-1.5-flash-exp-0827" - ), - { behavior: ["config"] } - ), - default: "gemini-1.5-flash-latest", - examples: ["gemini-1.5-flash-latest"], -}); - -const progressReader = code( - { - $id: "progressReader", - $metadata: { title: "Read progress so far" }, - context, - forkOutputs: true, - }, - { - progress: array(looperPlanType), - context: array(contextType), - }, - readProgress -); - -const taskAdder = code( - { - $id: "taskAdder", - $metadata: { title: "Add Task" }, - context: progressReader.outputs.context, - toAdd: task, - }, - { context: array(contextType) }, - addUserParts -); - -const plannerInstruction = ` -You are to create a precise plan for a given job. This plan will be executed by others and your responsibility is to produce a plan that reflects the job. - -Your output must be a valid JSON of the following format: - -\`\`\`json -{ - "max": "number, optional. Specifies how many iterations to make. Useful when the job specifies the upper limit the number of items in the list.", - "todo": [{ - "task": "string, The task description. Use action-oriented language, starting with a verb that fits the task." - }] - "doneMarker": "string, optional. The marker that will be used by others to signal completion." - "error": "string, optional. A description of why you're unable to create a plan" -} -\`\`\` - -There are four kinds of jobs that you can make plans for. - -1) The indefinite job. These are useful when there is not a definite completion condition, and is usually formulated with words like "indefinitely" or "forever". In such cases, the plan will look like an object without a "todo" property, with "max" set to a very large number: - -\`\`\`json -{ - "max": 100000000 -} -\`\`\` - -2) The step-by-step job. These are for situations when a distinct, known number of tasks can be discerned from the job. For example, when asked to write chapters of a book following an outline, there's a clear list of tasks that can be discerned (one "Write " per chapter). - -A plan for this kind of job will look like an object with "todo" items: - -\`\`\`json -{ - "todo": [ - { "task": "" -} -\`\`\` - -Common markers are "##STOP##" or "##DONE##", but could be different depending on a job. This type of the job is mutually exclusive with the step-by-step type, so the "todo" and "doneMarker" may never be specified together. - -When you are unable to create plan from the job, reply with: - -\`\`\`json -{ - "error": "" -} -\`\`\` - -`; - -const planGenerator = gemini.text({ - $id: "planGenerator", - $metadata: { title: "Generating Plan" }, - context: taskAdder.outputs.context, - systemInstruction: plannerInstruction, - responseMimeType: "application/json", - model, -}); - -export const planSchema = { - type: "object", - properties: { - max: { - type: "number", - description: "Maximum iterations to make, optional. Default is infinity", - }, - todo: { - type: "array", - description: - "Items in the plan, optional. Use this if the plan contains a definite, concrete list of items", - items: { - type: "object", - description: "The object that represent an item in the plan", - properties: { - task: { - type: "string", - description: - "The task description. Use action-oriented language, starting with a verb that fits the task", - }, - }, - }, - }, - doneMarker: { - type: "string", - description: - "The marker that will be used by others to signal completion of the job.", - }, - error: { - type: "string", - description: "Describe the reason why the plan generation failed", - }, - }, -} satisfies Schema; - -const planValidator = jsonKit.validateJson({ - $id: "validateJson", - $metadata: { title: "Validate Plan" }, - // TODO(aomarks) Cast because gemini's text output is possibly undefined, - // because in the tool-calling case no text is returned. Our type system is - // not smart enough to understand this at compile time (though either it - // should be, or gemini.text should not be polymorphic). - json: planGenerator.outputs.text as Value, - schema: planSchema, -}); - -// Exported for testing -export const planReaderFunction = ({ - context, - progress, -}: { - context: Context | Context[]; - // TODO(aomarks) Wouldn't need this broad type and the cast if validateJson - // propagated the given type/schema (like the cast node does). - progress: JsonSerializable; -}): { context: Context[]; done: Context[] } => { - const plans = ( - Array.isArray(progress) ? progress : [progress] - ) as LooperPlan[]; - const existing = Array.isArray(context) ? context : [context]; - if (!plans || !plans.length) { - throw new Error("Plan is required for Looper to function."); - } - try { - const current = plans[0]; - if (current.done) { - // TODO(aomarks) Here and below, the cast is because we don't support - // polymorphism in the code helper yet. - return { done: existing } as { context: Context[]; done: Context[] }; - } - const originalPlan = plans[plans.length - 1]; - let max = originalPlan.max; - const doneMarker = originalPlan.doneMarker; - if (!max) { - const planItems = originalPlan.todo?.length; - if (planItems) { - max = planItems + 1; - } else { - max = Infinity; - } - } - const contents = structuredClone(existing); - const count = plans.length; - if (count >= max) { - return { done: existing } as { context: Context[]; done: Context[] }; - } - if (current.todo && Array.isArray(current.todo)) { - const next = current.todo?.shift(); - if (!next) { - return { done: existing } as { context: Context[]; done: Context[] }; - } - // Sometimes, the Planner gets confused and puts the - // doneMaker together with todo. - // Quietly fix that problem here by removing doneMarker. - delete current.doneMarker; - contents.push({ - role: "$metadata", - type: "looper", - data: { ...current, next: next.task }, - }); - return { context: contents } as { context: Context[]; done: Context[] }; - } else if (doneMarker) { - contents.push({ - role: "$metadata", - type: "looper", - data: { doneMarker }, - }); - return { context: contents } as { context: Context[]; done: Context[] }; - } else if (max) { - const count = plans.length; - if (count >= max) { - return { done: existing } as { context: Context[]; done: Context[] }; - } - contents.push({ - role: "$metadata", - type: "looper", - data: { max }, - }); - return { context: contents } as { context: Context[]; done: Context[] }; - } - return { done: existing } as { context: Context[]; done: Context[] }; - } catch (e) { - const error = e as Error; - throw new Error(`Invalid plan, unable to proceed: ${error.message}`); - } -}; - -const planReader = code( - { - $id: "planReader", - $metadata: { title: "Read Plan" }, - context, - progress: converge( - progressReader.outputs.progress, - planValidator.outputs.json - ), - }, - { context: array(contextType), done: array(contextType) }, - planReaderFunction -); - -/** - * Given a context, removes all metadata from it - */ -const cleaner = code( - { - $id: "cleanUp", - $metadata: { title: "Clean up" }, - context: planReader.outputs.done, - }, - { context: array(contextType) }, - ({ context }) => { - if (!context) throw new Error("Context is required"); - return { context: context.filter((item) => item.role !== "$metadata") }; - } -); - -export default board({ - title: "Looper", - metadata: { - icon: "laps", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#looper", - }, - }, - description: - "A worker whose job it is to repeat the same thing over and over, until some condition is met or the max count of repetitions is reached.", - version: "0.0.1", - inputs: [ - inputNode({ context, task }, { id: "input-1" }), - inputNode({ model }, { title: "Model Input", id: "modelInput" }), - ], - outputs: [ - outputNode( - { done: output(cleaner.outputs.context, { title: "Done" }) }, - { title: "Exit", id: "exitOutput" } - ), - outputNode( - { loop: output(planReader.outputs.context, { title: "Loop" }) }, - { id: "output-2" } - ), - ], -}); diff --git a/packages/agent-kit/src/boards/repeater.ts b/packages/agent-kit/src/boards/repeater.ts deleted file mode 100644 index 27b1d350e00..00000000000 --- a/packages/agent-kit/src/boards/repeater.ts +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - annotate, - array, - board, - constant, - converge, - input, - loopback, - object, - outputNode, -} from "@breadboard-ai/build"; -import { code, invoke } from "@google-labs/core-kit"; -import { contextType } from "../context.js"; - -const inputContext = input({ - title: "Context", - type: array(contextType), - description: "Initial conversation context", - default: [], -}); - -const max = input({ - title: "Max", - description: - "The maximum number of repetitions to make (set to -1 to go infinitely)", - type: "number", - default: -1, - examples: [3], -}); - -const worker = input({ - title: "Worker", - description: "Worker to repeat", - type: annotate(object({}), { - behavior: ["board"], - }), -}); - -const counterContinue = loopback({ type: array(contextType) }); -const workerInvoke = invoke({ - $metadata: { title: "Invoke Worker" }, - $board: constant(worker), - context: converge(inputContext, counterContinue), -}); - -const workerExitOutput = outputNode( - { context: workerInvoke.unsafeOutput("exit") }, - { title: "Exit" } -); - -const counterCount = loopback({ type: "number" }); -const counter = code( - { - $metadata: { title: "Counter" }, - context: workerInvoke.unsafeOutput("context"), - count: converge(max, counterCount), - }, - { - continue: array(contextType), - stop: array(contextType), - count: "number", - }, - ({ context, count }) => { - const num = count - 1; - if (num !== 0) { - // TODO(aomarks) This cast is because we don't support optional outputs - // from the code helper yet. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return { continue: context, count: num } as any; - } - // TODO(aomarks) This cast is because we don't support optional outputs - // from the code helper yet. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return { stop: context } as any; - } -); -counterCount.resolve(counter.outputs.count); -counterContinue.resolve(counter.outputs.continue); - -const counterExitOutput = outputNode({ - context: counter.outputs.stop, -}); - -export default board({ - title: "Repeater", - description: - "A worker whose job it is to repeat the same thing over and over, until some condition is met or the max count of repetitions is reached.", - version: "0.0.1", - metadata: { - deprecated: true, - }, - inputs: { max, context: inputContext, worker }, - outputs: [workerExitOutput, counterExitOutput], -}); diff --git a/packages/agent-kit/src/boards/specialist.ts b/packages/agent-kit/src/boards/specialist.ts deleted file mode 100644 index 73abf1563ae..00000000000 --- a/packages/agent-kit/src/boards/specialist.ts +++ /dev/null @@ -1,367 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - annotate, - array, - board, - enumeration, - input, - inputNode, - object, - output, - outputNode, - starInputs, - Value, -} from "@breadboard-ai/build"; -import { code, coreKit } from "@google-labs/core-kit"; -import geminiKit from "@google-labs/gemini-kit"; -import { - addUserParts, - checkAreWeDoneFunction, - combineContextsFunction, - Context, - contextType, - functionCallType, - type LlmContent, - llmContentType, - looperProgressType, - looperTaskAdderFn, - readProgress as readProgressFn, - splitStartAdderFunction, -} from "../context.js"; -import { - boardInvocationArgsType, - boardInvocationAssemblerFunction, - functionDeclarationsFormatterFn, - functionOrTextRouterFunction, - type FunctionSignatureItem, - responseCollatorFunction, - type ToolResponse, - urlMapType, -} from "../function-calling.js"; -import boardToFunction from "./internal/board-to-function.js"; -import invokeBoardWithArgs from "./internal/invoke-board-with-args.js"; -import specialistDescriber from "./internal/specialist-describer.js"; -import { GenericBoardDefinition } from "@breadboard-ai/build/internal/board/board.js"; -import { substitute } from "../generated/substitute.js"; - -const inputs = starInputs({ type: object({}, "unknown") }); - -const tools = input({ - title: "Tools", - description: - "(Optional) Add tools to this list for the worker to use when needed", - type: annotate( - array(annotate(object({}, "unknown"), { behavior: ["board"] })), - { behavior: ["config"] } - ), - default: [], -}); - -const model = input({ - title: "Model", - description: "Choose the model to use for this specialist.", - type: annotate( - enumeration( - "gemini-1.5-flash-latest", - "gemini-1.5-pro-latest", - "gemini-1.5-pro-exp-0801", - "gemini-1.5-pro-exp-0827", - "gemini-1.5-flash-8b-exp-0827", - "gemini-1.5-flash-exp-0827" - ), - { - behavior: ["config"], - } - ), - default: "gemini-1.5-flash-latest", - examples: ["gemini-1.5-flash-latest"], -}); - -const substituteParams = substitute({ - $metadata: { - title: "Substitute Parameters", - description: "Performing parameter substitution, if needed.", - }, - "*": inputs, -}); - -const addTask = code( - { - $metadata: { - title: "Add Task", - description: "Adding task to the prompt.", - }, - context: substituteParams.outputs.in, - toAdd: substituteParams.outputs.task, - }, - { context: array(contextType) }, - addUserParts -); - -const readProgress = code( - { - $metadata: { title: "Read Progress so far" }, - context: substituteParams.outputs.in, - forkOutputs: false, - }, - { - progress: array(looperProgressType), - context: array(contextType), - }, - readProgressFn -); - -const addLooperTask = code( - { - $metadata: { - title: "Add Looper Task", - description: "If there is a pending Looper task, add it.", - }, - context: addTask.outputs.context, - progress: readProgress.outputs.progress, - }, - { - context: array(contextType), - }, - looperTaskAdderFn -); - -const addSplitStart = code( - { - $metadata: { - title: "Add Split Start", - description: "Marking the start of parallel processing in the context", - }, - context: addLooperTask.outputs.context, - }, - { - id: "string", - context: array(contextType), - }, - splitStartAdderFunction -); - -const boardToFunctionWithContext = coreKit.curry({ - $metadata: { - title: "Add Context", - description: "Adding context to the board to function converter", - }, - $board: boardToFunction, - context: addSplitStart.outputs.context, -}); - -const turnBoardsToFunctions = coreKit.map({ - $id: "turnBoardsToFunctions", - $metadata: { - title: "Turn Boards into Functions", - description: "Turning provided boards into functions", - }, - board: boardToFunctionWithContext.outputs.board, - list: tools, -}); - -const formatFunctionDeclarations = code( - { - $id: "formatFunctionDeclarations", - $metadata: { - title: "Format Function Declarations", - description: "Formatting the function declarations", - }, - // TODO(aomarks) Cast needed because coreKit.map doesn't know the schema of - // the board that was passed to it (interfaces would fix this). - list: turnBoardsToFunctions.outputs.list as Value, - routes: substituteParams.outputs.outs, - }, - { - tools: array("unknown"), - urlMap: urlMapType, - }, - functionDeclarationsFormatterFn -); - -const generator = geminiKit.text({ - $metadata: { - title: "Gemini API Call", - description: "Applying Gemini to do work", - }, - systemInstruction: substituteParams.outputs.persona, - tools: formatFunctionDeclarations.outputs.tools, - context: addLooperTask.outputs.context, - model, -}); - -const routeToFunctionsOrText = code( - { - $id: "router", - $metadata: { - title: "Router", - description: "Routing to either function call invocation or text reply", - }, - // TODO(aomarks) Our types and gemini's types seem not aligned. - context: generator.outputs.context as Value, - }, - { - context: llmContentType, - text: "string", - functionCalls: array(functionCallType), - }, - functionOrTextRouterFunction -); - -const assembleInvocations = code( - { - $id: "assembleBoardInvoke", - $metadata: { - title: "Assemble Tool Invoke", - description: "Assembling tool invocation based on Gemini response", - }, - urlMap: formatFunctionDeclarations.outputs.urlMap, - context: routeToFunctionsOrText.outputs.context, - functionCalls: routeToFunctionsOrText.outputs.functionCalls, - }, - { - list: array(boardInvocationArgsType), - routes: array("string"), - }, - boardInvocationAssemblerFunction -); - -const mapInvocations = coreKit.map({ - $metadata: { - title: "Invoke Tools in Parallel", - description: "Invoking tools in parallel", - }, - list: assembleInvocations.outputs.list, - board: invokeBoardWithArgs, -}); - -const formatToolResponse = code( - { - $metadata: { - title: "Format Tool Response", - description: "Formatting tool response", - }, - // TODO(aomarks) There's inconsistency between use of LlmContent and Context - // across these nodes. Sometimes we need to cast to the other type because - // of that. - context: addSplitStart.outputs.context as Value, - response: mapInvocations.outputs.list as Value, - generated: generator.outputs.context as Value, - }, - {}, - responseCollatorFunction -); - -const addToolResponseToContext = code( - { - $metadata: { - title: "Add Tool Response", - description: "Adding tool response to context", - }, - // TODO(aomarks) A nicer way to do star wiring. Also, why does the input port have - // to be "" instead of "*" (it doesn't work with "*"). - "": formatToolResponse.unsafeOutput("*"), - }, - { - context: array(contextType), - }, - combineContextsFunction -); - -const routeToolOutput = code( - { - $metadata: { - title: "Route Tool Output", - description: "Routing tool output as needed", - }, - context: addToolResponseToContext.outputs.context, - routes: assembleInvocations.outputs.routes, - }, - {}, - ({ context, routes }) => { - const out: Record = {}; - let hasRoutes = false; - for (const route of routes) { - out[`p-${route}`] = context; - hasRoutes = true; - } - if (!hasRoutes) { - return { out: context }; - } - for (let i = context.length - 1; i >= 0; i--) { - const item = context[i]; - if (item.role === "model") { - item.parts = item.parts.filter((part) => !("functionCall" in part)); - break; - } - } - return out; - } -); - -const toolOutput = outputNode({ - $metadata: { - title: "Tool Output", - description: "Return tool results as output", - }, - "": routeToolOutput.unsafeOutput("*"), -}); - -const areWeDoneChecker = code( - { - $metadata: { - title: "Done Check", - description: "Checking for the 'Done' marker", - }, - context: addLooperTask.outputs.context, - generated: routeToFunctionsOrText.outputs.context, - text: routeToFunctionsOrText.outputs.text, - }, - { - context: array(contextType), - }, - checkAreWeDoneFunction -); - -const mainOutput = outputNode({ - out: output(areWeDoneChecker.outputs.context, { title: "Context out" }), -}); - -export default board({ - title: "Specialist", - metadata: { - icon: "smart-toy", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/agents/#specialist", - }, - }, - version: "2.1.0", - description: - "Given instructions on how to act, makes a single LLM call, optionally invoking tools.", - inputs: [ - inputNode({ - "*": inputs, - }), - inputNode( - { tools }, - { - title: "Tools Input", - description: "Specify the tools to use", - } - ), - inputNode( - { model }, - { - title: "Model Input", - description: "Ask which model to use", - } - ), - ], - outputs: [toolOutput, mainOutput], - describer: specialistDescriber as GenericBoardDefinition, -}); diff --git a/packages/agent-kit/src/boards/structured-worker.ts b/packages/agent-kit/src/boards/structured-worker.ts deleted file mode 100644 index 6eaac029473..00000000000 --- a/packages/agent-kit/src/boards/structured-worker.ts +++ /dev/null @@ -1,266 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - annotate, - array, - board, - constant, - converge, - input, - inputNode, - jsonSchema, - loopback, - output, - outputNode, - string, - Value, -} from "@breadboard-ai/build"; -import { code, passthrough } from "@google-labs/core-kit"; -import geminiKit from "@google-labs/gemini-kit"; -import { jsonKit } from "@google-labs/json-kit"; -import { promptTemplate } from "@google-labs/template-kit"; -import { type Context, contextType } from "../context.js"; -import { OutputPort } from "@breadboard-ai/build/internal/common/port.js"; - -const context = input({ - title: "Context", - type: array(contextType), - default: [], - examples: [[{ role: "user", parts: [{ text: "the universe within us" }] }]], -}); - -const instruction = input({ - title: "Instruction", - type: annotate(string({ format: "multiline" }), { behavior: ["config"] }), - examples: [ - `You are a brilliant poet who specializes in two-line rhyming poems. -Given any topic, you can quickly whip up three two-line rhyming poems about it. -Look at the topic below and do your magic`, - ], -}); - -const schema = input({ - title: "Schema", - description: "The schema to convert to schemish.", - type: annotate(jsonSchema, { behavior: ["config"] }), - default: {}, - examples: [ - { - type: "object", - properties: { - poems: { - type: "array", - items: { - type: "object", - properties: { - inspiration: { - type: "string", - description: "The inspiration behind the poem", - }, - poem: { - type: "string", - description: "The poem itself", - }, - }, - }, - }, - }, - }, - ], -}); - -const schemish = jsonKit.schemish({ - $id: "schemish", - $metadata: { - title: "Schemish", - description: "Converting JSON schema to a more compact format", - }, - schema, -}); - -const format = promptTemplate({ - $id: "format", - $metadata: { - title: "Reply Structure Formatter", - description: "Formatting the reply structure for the agent.", - }, - template: `Reply as valid JSON of the following format: - -\`\`\`json -{{schemish}} -\`\`\` -`, - schemish: schemish.outputs.schemish, -}); - -const buildContext = code( - { - $id: "buildContext", - $metadata: { - title: "Build Context", - description: "Building the context for the agent", - }, - context, - instruction, - format, - }, - { context: array(contextType) }, - ({ context, format, instruction }) => { - if (!Array.isArray(context)) { - // A clever trick. Let's see if this works - // A user can supply context as either ContextItem[] or as non-array. - // When it's not an array, let's just conjure up the proper ContextItem[] - // from that. - const text = - typeof context === "string" ? context : JSON.stringify(context); - context = [{ role: "user", parts: [{ text }] }]; - } - const list = context || []; - if (list.length > 0) { - const last = list[list.length - 1]; - if (last.role === "user") { - // A trick: the instruction typically sits in front of the actual task - // that the user requests. So do just that -- add it at the front of the - // user part list, rather than at the end. - last.parts.unshift({ text: instruction }, { text: format }); - return { context: list }; - } - } - return { - context: [ - ...list, - { role: "user", parts: [{ text: instruction }, { text: format }] }, - ], - } as const; - } -); - -const initialValues = passthrough({ - $id: "initialValues", - $metadata: { - title: "Initial Values", - description: "Populating initial values for the counter", - }, - count: 5, - error: "stub", -}); - -const countLoopback = loopback({ type: "number" }); -const errorLoopback = loopback({ type: "unknown" }); - -const count = code( - { - $id: "count", - $metadata: { - title: "Counter", - description: "Counting the JSON healing iteration", - }, - count: converge( - // TODO(aomarks) Casts required because we probably want a helper for - // passthrough that preserves types better. - initialValues.outputs.count as OutputPort, - countLoopback - ), - error: converge( - initialValues.outputs.error as OutputPort, - errorLoopback - ), - context: constant(buildContext.outputs.context), - }, - { continue: array(contextType), count: "number", stop: "string" }, - ({ context, error, count }) => { - // TODO(aomarks) Casts required until code() supports polymorphism better. - type TempUnsafeResult = { - continue: Context[]; - count: number; - stop: string; - }; - const num = count - 1; - if (num != 0) { - return { continue: context, count: num } as TempUnsafeResult; - } - return { stop: error } as TempUnsafeResult; - } -); -countLoopback.resolve(count.outputs.count); - -const generate = geminiKit.text({ - $id: "generate", - $metadata: { - title: "Generate", - logLevel: "info", - description: "Generating an answer", - }, - context: count.outputs.continue, - text: "unused", // A gross hack (see TODO in gemini-generator.ts) -}); - -const validate = jsonKit.validateJson({ - $id: "validate", - $metadata: { - title: "Validate JSON", - logLevel: "info", - description: "Checking my work", - }, - // TODO(aomarks) Cast is required because of the polymorphic signature of - // gemini text. - json: generate.outputs.text as Value, - schema: constant(schema), -}); -errorLoopback.resolve(validate.outputs.$error); - -const assembleContext = code( - { - $id: "assembleContext", - $metadata: { - title: "Assemble Context", - description: "Assembling the context for the agent", - }, - context: buildContext.outputs.context, - json: validate.outputs.json, - }, - { context: array(contextType) }, - ({ context, json }) => { - if (!context) throw new Error("Context is required"); - return { - context: [ - ...context, - { role: "model", parts: [{ text: JSON.stringify(json) }] }, - ] as const, - }; - } -); - -export default board({ - title: "Structured Worker", - description: "A worker who outputs structure data (JSON) provided a schema.", - version: "0.0.1", - metadata: { - deprecated: true, - }, - inputs: inputNode({ context, instruction, schema }), - outputs: [ - outputNode( - { - $error: validate.outputs.$error, - context: count.outputs.stop, - }, - { - id: "errorOutput", - title: "Error Output", - description: "Displaying error output, giving up on JSON healing", - } - ), - outputNode({ - json: output(validate.outputs.json, { - title: "JSON", - description: "The validated JSON.", - }), - context: assembleContext.outputs.context, - }), - ], -}); diff --git a/packages/agent-kit/src/boards/worker.ts b/packages/agent-kit/src/boards/worker.ts deleted file mode 100644 index 2cce9856b3f..00000000000 --- a/packages/agent-kit/src/boards/worker.ts +++ /dev/null @@ -1,133 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { annotate, array, board, input, string } from "@breadboard-ai/build"; -import { NewNodeFactory, NewNodeValue } from "@google-labs/breadboard"; -import { code } from "@google-labs/core-kit"; -import gemini from "@google-labs/gemini-kit"; -import { Context, contextType } from "../context.js"; - -export type WorkerType = NewNodeFactory< - { - /** - * The context to use for the worker. - */ - context?: NewNodeValue; - /** - * The instruction we want to give to the worker so that shapes its - * character and orients it a bit toward the task we want to give it. - */ - instruction: NewNodeValue; - /** - * The stop sequences to use for the worker. - */ - stopSequences?: NewNodeValue; - }, - { - /** - * The context after generation. Pass this to the next agent when chaining - * them together. - */ - context: NewNodeValue; - /** - * The output from the agent. Use this to just get the output without any - * previous context. - */ - text: NewNodeValue; - } ->; - -const context = input({ - title: "Context", - type: array(contextType), - examples: [[{ role: "user", parts: [{ text: "the universe within us" }] }]], -}); - -const instruction = input({ - title: "Instruction", - type: annotate(string({ format: "multiline" }), { behavior: ["config"] }), - examples: [ - `You are a brilliant poet who specializes in two-line rhyming poems. -Given any topic, you can quickly whip up a two-line rhyming poem about it. -Look at the topic below and do your magic`, - ], -}); - -const stopSequences = input({ - title: "Stop Sequences", - type: annotate(array("string"), { behavior: ["config"] }), - default: [], -}); - -const contextBuilder = code( - { $metadata: { title: "Build Context" }, context, instruction }, - { context: array(contextType) }, - ({ context, instruction }) => { - if (typeof context === "string") { - // TODO(aomarks) Let's remove this and make all context array ports - // totally consistent in their schemas, and create some helpers for - // quickly doing e.g. string -> user text part. - context = [{ role: "user", parts: [{ text: context }] }]; - } - const list = context ?? []; - if (list.length > 0) { - const last = list[list.length - 1]; - if (last.role === "user") { - // A trick: the instruction typically sits in front of the actual task - // that the user requests. So do just that -- add it at the front of the - // user part list, rather than at the end. - last.parts.unshift({ text: instruction }); - return { context: list }; - } - } - return { - context: [ - ...list, - { role: "user", parts: [{ text: instruction }] }, - ] as const, - }; - } -); - -const generator = gemini.text({ - context: contextBuilder.outputs.context, - stopSequences, -}); - -const contextAssembler = code( - { - $metadata: { title: "Assemble Context" }, - context: contextBuilder.outputs.context, - generated: generator.outputs.context, - }, - { context: array(contextType) }, - ({ context, generated }) => { - if (!context) throw new Error("Context is required"); - return { - context: [ - ...context, - // TODO(aomarks) The types shared by gemini-kit and agent-kit have some - // (probably minor) incompatibility. They should both use a common type - // defined in some package. - generated as Context, - ], - }; - } -); - -export default board({ - title: "Worker", - description: "The essential Agent building block", - version: "0.0.1", - metadata: { - deprecated: true, - }, - inputs: { context, instruction, stopSequences }, - outputs: { - context: contextAssembler.outputs.context, - text: generator.outputs.text, - }, -}); diff --git a/packages/agent-kit/src/context.ts b/packages/agent-kit/src/context.ts deleted file mode 100644 index 65edd3fb719..00000000000 --- a/packages/agent-kit/src/context.ts +++ /dev/null @@ -1,648 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - annotate, - anyOf, - array, - enumeration, - intersect, - object, - optional, - toJSONSchema, - unsafeType, -} from "@breadboard-ai/build"; -import type { ConvertBreadboardType } from "@breadboard-ai/build/internal/type-system/type.js"; -import { code } from "@google-labs/breadboard"; - -export const textPartType = object({ text: "string" }); -export type TextPart = ConvertBreadboardType; - -export const functionCallType = object({ - name: "string", - args: object({}, "string"), -}); -export type FunctionCall = ConvertBreadboardType; - -export const functionCallPartType = object({ - functionCall: functionCallType, -}); -export type FunctionCallPart = ConvertBreadboardType< - typeof functionCallPartType ->; - -export const llmContentRoleType = enumeration("user", "model", "tool"); -export type LlmContentRole = ConvertBreadboardType; - -export const llmContentType = annotate( - object({ - role: optional(llmContentRoleType), - parts: array(anyOf(textPartType, functionCallPartType)), - }), - { behavior: ["llm-content"] } -); - -export type LlmContent = ConvertBreadboardType; - -export const splitMarkerDataType = object({ - /** - * There are three types of split markers: - * - start: the beginning of the split - * - next: the separator between the split parts - * - end: the end of the split - */ - type: enumeration("start", "next", "end"), - /** - * Unique identifier for the split. - */ - id: "string", -}); -export type SplitMarkerData = ConvertBreadboardType; - -/** - * Provides support for storing multiple parallel contexts within - * a single context. - * - * The split marker allows representing multiple parallel contexts - * as one sequence by separating them with split markers. - * - * The sequence begins with a split marker of type "start", - * followed by one or more split markers of type "separator", - * and ends with a split marker of type "end". - * - * To allow nesting of split markers, a unique identifier is - * assigned to all split markers that belong to the same split. - */ -export const splitMetadataType = object({ - type: enumeration("split"), - data: splitMarkerDataType, -}); -export type SplitMetadata = ConvertBreadboardType; - -export const looperPlanType = object({ - /** - * Maximum iterations to make. This can be used to create simple - * "repeat N times" loops. - */ - max: optional("number"), - /** - * Plan items. Each item represents one trip down the "Loop" output, and - * at the end of the list, the "Context Out". - */ - todo: optional( - array( - object({ - task: "string", - }) - ) - ), - /** - * The marker that will be used by others to signal completion of the job. - */ - doneMarker: optional("string"), - /** - * Indicator that this job is done. - */ - done: optional("boolean"), - /** - * Whether to append only the last item in the loop to the context or all - * of them. - */ - appendLast: optional("boolean"), - /** - * Whether to return only last item from the context as the final product - * or all of them; - */ - returnLast: optional("boolean"), - /** - * The next task. - */ - next: optional("string"), -}); -export type LooperPlan = ConvertBreadboardType; - -export const looperMetadataType = object({ - type: enumeration("looper"), - data: looperPlanType, -}); -export type LooperMetadata = ConvertBreadboardType; - -const metadataBase = object({ role: enumeration("$metadata") }); -export const metadataType = anyOf( - intersect(metadataBase, looperMetadataType), - intersect(metadataBase, splitMetadataType) -); -export type Metadata = ConvertBreadboardType; - -// TODO(aomarks) intersect currently knows it can't handle cases like this and -// throws. It's the case where the two intersected objects both have the same -// property. E.g. {role: "$metadata"} & {role?: "$metadata"} should be -// {role: "$metadata"}. -export const looperProgressType = unsafeType< - ConvertBreadboardType & { next: string } ->( - (() => { - const schema = toJSONSchema(looperPlanType); - const required = (schema.required as string[] | undefined) ?? []; - if (!required.includes("next")) { - required.push("next"); - schema.required = required; - } - return schema; - })() -); -export type LooperProgress = ConvertBreadboardType; - -export const contextType = annotate(anyOf(llmContentType, metadataType), { - behavior: ["llm-content"], -}); -export type Context = ConvertBreadboardType; - -/** - * Type helper for wrapping `code` functions. - * @param f -- code function - * @returns -- code function - */ -export const fun = < - In = Record, - Out = Record, ->( - f: (inputs: In) => Out -) => { - return f; -}; - -export const addUserParts = ({ - context, - toAdd, -}: { - context: Context | Context[]; - toAdd: LlmContent | string; -}): { context: Context[] } => { - if (!context) throw new Error("Context is required"); - const existing = Array.isArray(context) ? context : [context]; - const incoming = toAdd; - if (typeof incoming === "string") { - return { context: existing }; - } - if (!incoming.parts) { - const containsUserRole = - existing.filter( - (item) => item.role !== "model" && item.role !== "$metadata" - ).length > 0; - if (!containsUserRole) { - return { - context: [ - ...existing, - { role: "user", parts: [{ text: "Do your magic" }] }, - ], - }; - } - return { context: existing }; - } - if (!incoming.role) { - incoming.role = "user"; - } - const last = existing[existing.length - 1]; - if (!last) { - return { context: [incoming] }; - } - if (last.role !== incoming.role) { - return { context: [...existing, incoming] }; - } else { - const result = structuredClone(existing) as LlmContent[]; - const index = result.length - 1; - result[index].parts.push(...incoming.parts); - return { context: result }; - } -}; - -export const userPartsAdder = code(addUserParts); - -export const readProgress = ({ - context, - forkOutputs, -}: { - context: Context | Context[]; - forkOutputs: boolean; -}): { - progress: LooperProgress[]; - context: Context[]; -} => { - const fork = forkOutputs; - const existing = Array.isArray(context) ? context : [context]; - const progress: LooperPlan[] = []; - // Collect all metadata entries in the context. - // Gives us where we've been and where we're going. - for (let i = existing.length - 1; i >= 0; i--) { - const item = existing[i]; - if (item.role === "$metadata" && item.type === "looper") { - progress.push(item.data); - } - } - // TODO(aomarks) Casts required until code() supports polymorphism better. - type TempUnsafeResult = { - progress: LooperProgress[]; - context: Context[]; - }; - if (fork) { - if (progress.length) { - return { progress } as TempUnsafeResult; - } else { - return { context } as TempUnsafeResult; - } - } else { - return { context, progress } as TempUnsafeResult; - } -}; - -export const progressReader = code(readProgress); - -export const looperTaskAdderFn = ({ - context, - progress, -}: { - context: Context[]; - progress: LooperProgress[]; -}): { context: Context[] } => { - const contents = Array.isArray(context) ? context : [context]; - const plans = Array.isArray(progress) ? progress : [progress]; - const last = plans[0]; - if (!last || !last.next) { - return { context }; - } - // @ts-expect-error -- TS doesn't know findLastIndex exists - const lastLooperMarker = contents.findLastIndex( - (item: Context) => item.role === "$metadata" && item.type === "looper" - ); - if (lastLooperMarker >= 0) { - const pastLooper = contents.slice(lastLooperMarker); - const hasModel = pastLooper.some((item) => item.role === "model"); - if (hasModel) { - return { context: contents }; - } - } - contents.push({ role: "user", parts: [{ text: last.next }] }); - return { context: contents }; -}; -export const looperTaskAdder = code(looperTaskAdderFn); - -export const contextBuilder = code(({ context, instruction }) => { - if (typeof context === "string") { - // A clever trick. Let's see if this works - // A user can supply context as either ContextItem[] or as a string. - // When it's a string, let's just conjure up the proper ContextItem[] - // from that. - context = [{ role: "user", parts: [{ text: context }] }]; - } - const list = (context as unknown[]) || []; - if (list.length > 0) { - const last = list[list.length - 1] as LlmContent; - if (last.role === "user") { - // A trick: the instruction typically sits in front of the actual task - // that the user requests. So do just that -- add it at the front of the - // user part list, rather than at the end. - last.parts.unshift({ text: instruction as string }); - return { context: list }; - } - } - return { - context: [...list, { role: "user", parts: [{ text: instruction }] }], - }; -}); - -export const contextBuilderWithoutSystemInstruction = code(({ context }) => { - if (typeof context === "string") { - // A clever trick. Let's see if this works - // A user can supply context as either ContextItem[] or as a string. - // When it's a string, let's just conjure up the proper ContextItem[] - // from that. - context = [{ role: "user", parts: [{ text: context }] }]; - } - const list = (context as unknown[]) || []; - return { context: list }; -}); - -export const contextAssembler = code(({ context, generated }) => { - if (!context) throw new Error("Context is required"); - return { context: [...(context as LlmContent[]), generated as LlmContent] }; -}); - -export const checkAreWeDoneFunction = fun(({ context, generated }) => { - if (!context) throw new Error("Context is required"); - if (!generated) throw new Error("Generated is required"); - const c = context as Context[]; - const g = generated as LlmContent; - // are there any doneMakers in the context? - let doneMarker: string | null = null; - for (let i = 0; i < c.length; ++i) { - const item = c[i]; - if (item.role === "$metadata" && item.type === "looper") { - const plan = item.data as LooperPlan; - if (plan.doneMarker) { - doneMarker = plan.doneMarker; - break; - } - } - } - - if (!doneMarker) { - return { context: [...c, g] }; - } - - // does generated content contain the markers? - let containsMarkers = false; - for (let i = 0; i < g.parts.length; ++i) { - const part = g.parts[i]; - if ("text" in part && part.text.includes(doneMarker)) { - containsMarkers = true; - // remove marker from generated - part.text = part.text.replaceAll(doneMarker, "").trim(); - break; - } - } - if (!containsMarkers) { - return { context: [...c, g] }; - } - - const metadata: Metadata = { - role: "$metadata", - type: "looper", - data: { - done: true, - }, - }; - return { context: [...c, g, metadata] }; -}); - -export const checkAreWeDone = code(checkAreWeDoneFunction); - -/** - * Given a context, decides if we should skip our turn when the earlier - * workers signaled that they are done. - */ -export const skipIfDoneFunction = fun(({ context }) => { - if (!context) throw new Error("Context is required"); - const c = context as Context[]; - // are there any done:true in the context? - let done = false; - for (let i = 0; i < c.length; ++i) { - const item = c[i]; - if (item.role === "$metadata" && item.type === "looper") { - const plan = item.data as LooperPlan; - if (plan.done) { - done = true; - break; - } - } - } - if (done) { - return { done: context }; - } else { - return { context }; - } -}); - -export const skipIfDone = code(skipIfDoneFunction); - -/** - * Given a context, adds a metadata block that contains the - * split start marker. - */ -export const splitStartAdderFunction = ({ - context, -}: { - context: Context[]; -}): { id: string; context: Context[] } => { - if (!context) throw new Error("Context is required"); - const c = context; - const id = Math.random().toString(36).substring(7); - const metadata: Metadata = { - role: "$metadata", - type: "split", - data: { - type: "start", - id, - }, - }; - return { context: [...c, metadata], id }; -}; - -export const splitStartAdder = code(splitStartAdderFunction); - -export type SplitScanResult = [id: string, index: number]; - -/** - * Given a bunch of contexts, combines them all into one. - * A couple of scenarios are supported: - * - "The single split start context". Happens when Specialist invokes one - * or more tools, but the tools don't emit any open split markers. - * In this situation, the first context ("context-0") will have a start marker, - * with no other context containing any open markers. - * - "First context as a preamble". Happens when Specialist invokes one or more - * tools, and all tools consume this context. In this situation, the first - * context ("context-0") will end at the split start marker, and all other - * context will contain this context as a preamble, followed by their own - * generated context. - * - "Ad hoc". Happens when Joiner is used to combine multiple - * contexts. In this situation, there are multiple open - * markers, but no matching preamble in the first context. - * - "Simple". Happens when Joiner combines multiple context with no open - * split markers. - * - * Strategies for each scenario: - * - "Single split start context". Add "next" split marker between each context - * and an "end" marker at the end. - * - "First context as a preamble". Slice contexts other than first at the - * preamble index and concatenate them, adding "next" and "end" markers. - * - "Ad hoc". Concatenate all contexts as-is, no markers. - * - "Simple". Concatenate all contexts as-is, adding "start", "next" and "end" - * markers. - */ -export const combineContextsFunction = fun( - ({ merge, ...inputs }): { context: Context[] } => { - const entries = Object.entries(inputs).sort() as [string, Context[]][]; - if (merge) { - const context: Context[] = []; - const parts: LlmContent["parts"] = []; - for (const [, input] of entries) { - const c = asContextArray(input); - let lastIndex = c.length - 1; - let last; - do { - last = c[lastIndex--]; - } while (lastIndex >= 0 && last.role === "$metadata"); - if (last) { - parts.push(...(last as LlmContent).parts); - } - } - context.push({ parts, role: "user" }); - return { context }; - } else { - let mode: "single" | "preamble" | "adhoc" | "simple"; - const [f, ...rest] = entries; - if (!f) { - return { context: [] }; - } - const first = asContextArray(f[1]); - const firstOpenSplits = scanForSplits(first); - const preambleIndices: number[] = []; - for (const [, input] of rest) { - const c = asContextArray(input); - const hasOpenSplits = scanForSplits(c); - if (hasOpenSplits) { - preambleIndices.push(hasOpenSplits[1]); - } - } - if (!firstOpenSplits) { - if (preambleIndices.length === 0) { - mode = "simple"; - } else { - mode = "adhoc"; - } - } else { - const preamblesMatch = - preambleIndices.length > 0 && - preambleIndices.every((value) => value === firstOpenSplits[1]); - if (preamblesMatch) { - mode = "preamble"; - } else { - if (firstOpenSplits[1] === first.length - 1) { - mode = "single"; - } else { - mode = "adhoc"; - } - } - } - const context: Context[] = []; - if (mode === "adhoc") { - for (const [, input] of entries) { - const c = asContextArray(input); - context.push(...c); - } - return { context }; - } else if (mode === "simple") { - const splitId = Math.random().toString(36).substring(7); - context.push({ - role: "$metadata", - type: "split", - data: { type: "start", id: splitId }, - }); - for (const [, input] of entries) { - const c = asContextArray(input); - context.push(...c); - context.push({ - role: "$metadata", - type: "split", - data: { type: "next", id: splitId }, - }); - } - } else if (mode === "preamble") { - const preambleIndex = firstOpenSplits?.[1] || 0; - const preamble = entries[0][1].slice(0, preambleIndex + 1); - context.push(...preamble); - const splitId = (preamble[preamble.length - 1] as SplitMetadata).data - .id; - for (const [, input] of entries) { - let c = asContextArray(input); - if (preambleIndex >= 0) { - c = c.slice(preambleIndex + 1); - } - if (c.length) { - context.push(...c); - context.push({ - role: "$metadata", - type: "split", - data: { type: "next", id: splitId }, - }); - } - } - } else if (mode === "single") { - const splitId = (first[first.length - 1] as SplitMetadata).data.id; - context.push(...first); - for (const [, input] of rest) { - const c = asContextArray(input); - context.push(...c); - context.push({ - role: "$metadata", - type: "split", - data: { type: "next", id: splitId }, - }); - } - } - const last = context[context.length - 1] as SplitMetadata; - last.data.type = "end"; - return { context }; - } - - function asContextArray(input: Context | Context[]): Context[] { - return Array.isArray(input) ? input : [input]; - } - - function scanForSplits(c: Context[]): SplitScanResult | null { - const stack: SplitScanResult[] = []; - for (const [i, item] of c.entries()) { - if (item.role !== "$metadata") continue; - if (item.type !== "split") continue; - if (item.data.type === "start") { - stack.push([item.data.id, i]); - } - if (item.data.type === "end") { - const [id] = stack.pop() || []; - if (id !== item.data.id) { - console.warn( - "Split integrity error: mismatched split start/end markers. Start:", - id, - "End:", - item.data.id - ); - return null; - } - } - } - return stack.pop() || null; - } - } -); -export const combineContexts = code(combineContextsFunction); - -/** - * Takes a single context and splits it into multiple contexts using the - * split markers. - */ -export const splitContextsFunction = fun(({ context }) => { - if (!context) throw new Error("Context is required"); - const c = asContextArray(context); - const last = c[c.length - 1]; - if ( - last.role !== "$metadata" || - last.type !== "split" || - last.data.type !== "end" - ) { - return { context: c }; - } - const contexts: Context[][] = []; - let current: Context[] = []; - for (const item of c) { - if (item.role === "$metadata" && item.type === "split") { - if (item.data.type === "start") { - current = []; - } else if (item.data.type === "end") { - contexts.push(current); - } - } else { - current.push(item); - } - } - const result: Record = Object.fromEntries( - contexts.map((c, i) => [`context-${i}`, c]) - ); - return result; - - function asContextArray(input: unknown): Context[] { - return Array.isArray(input) ? input : [input]; - } -}); diff --git a/packages/agent-kit/src/function-calling.ts b/packages/agent-kit/src/function-calling.ts deleted file mode 100644 index 18f6c8995a1..00000000000 --- a/packages/agent-kit/src/function-calling.ts +++ /dev/null @@ -1,326 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { array, jsonSchema, object, optional } from "@breadboard-ai/build"; -import { - type ConvertBreadboardType, - type JsonSerializable, -} from "@breadboard-ai/build/internal/type-system/type.js"; -import { - type GraphDescriptor, - type OutputValues, - type Schema, - code, -} from "@google-labs/breadboard"; -import { - type Context, - type FunctionCall, - type LlmContent, - fun, - llmContentType, -} from "./context.js"; - -export const functionOrTextRouterFunction = ({ - context, -}: { - context: LlmContent; -}): { context: LlmContent; text: string; functionCalls: FunctionCall[] } => { - type TempUnsafeResult = { - context: LlmContent; - text: string; - functionCalls: FunctionCall[]; - }; - if (!context) throw new Error("Context is a required input"); - const item = context; - const functionCallParts = item.parts - .filter((part) => "functionCall" in part) - .map((part) => part.functionCall); - if (functionCallParts.length === 0) { - const textPart = item.parts.find((part) => "text" in part); - if (!textPart) throw new Error("No text or function call found in context"); - return { context, text: textPart.text } as TempUnsafeResult; - } - return { context, functionCalls: functionCallParts } as TempUnsafeResult; -}; - -export const functionOrTextRouter = code(functionOrTextRouterFunction); - -export const functionCallFlagsType = object({ - inputLLMContent: optional("string"), - inputLLMContentArray: optional("string"), - outputLLMContent: optional("string"), - outputLLMContentArray: optional("string"), -}); - -export type FunctionCallFlags = ConvertBreadboardType< - typeof functionCallFlagsType ->; - -export const urlMapType = object( - {}, - object({ url: "string", flags: functionCallFlagsType }) -); -export type URLMap = ConvertBreadboardType; - -export const boardInvocationArgsType = object( - { - $board: "string", - $flags: functionCallFlagsType, - }, - "unknown" -); -export type BoardInvocationArgs = ConvertBreadboardType< - typeof boardInvocationArgsType ->; - -export const boardInvocationAssemblerFunction = ({ - functionCalls, - urlMap, -}: { - functionCalls: FunctionCall[]; - urlMap: URLMap; -}): { list: BoardInvocationArgs[]; routes: string[] } => { - if (!functionCalls) { - throw new Error("Function call array is a required input"); - } - if (!urlMap) { - throw new Error("URL map is a required input"); - } - const calls = functionCalls; - if (calls.length === 0) { - throw new Error("Function call array must not be empty."); - } - const list: BoardInvocationArgs[] = []; - const routes: string[] = []; - for (const call of calls) { - const item = urlMap[call.name]; - if (!item) { - throw new Error( - `Invalid function call: "${call.name}". More than likely, the LLM hallucinated a function call that doesn't exist.` - ); - } - if (!item.url) { - routes.push(call.name); - continue; - } - const $board = item.url; - const $flags = item.flags; - const llmContentProperty = - $flags.inputLLMContent || $flags.inputLLMContentArray; - const invokeArgs: BoardInvocationArgs = { $board, $flags, ...call.args }; - if (llmContentProperty) { - // convert args into LLMContent. - const args = call.args; - const text = args[llmContentProperty] || ""; - const parts = [{ text }]; - const llmContent: LlmContent = { parts, role: "user" }; - if ($flags.inputLLMContentArray) { - invokeArgs[llmContentProperty] = [llmContent]; - } else { - invokeArgs[llmContentProperty] = llmContent; - } - } - list.push(invokeArgs); - } - return { list, routes }; -}; - -export const resultFormatterFunction = fun(({ result, flags }) => { - let contentDetected = false; - const inputs = result as OutputValues; - const item: Context[] = []; - const f = flags as FunctionCallFlags; - if (f) { - if (f.outputLLMContent) { - const content = inputs[f.outputLLMContent] as Context; - content.role = "tool"; - item.push(content); - contentDetected = true; - } else if (f.outputLLMContentArray) { - const contentArray = inputs[f.outputLLMContentArray] as Context[]; - contentArray.forEach((content) => { - if (content.role !== "$metadata") { - content.role = "tool"; - } - item.push(content); - }); - contentDetected = true; - } - } else { - // TODO: Deprecate and remove. This is the old way of - // detecting LLMContent (before flags were introduced). - // There should only be a handful of tools that use this. - for (const key in inputs) { - const input = inputs[key] as { content: LlmContent }; - if (input !== null && typeof input === "object" && "content" in input) { - // Presume that this is an LLMContent - const content = input.content; - // Let's double check... - if (content.parts && Array.isArray(content.parts)) { - content.role = "tool"; - item.push(content); - contentDetected = true; - } - } - } - } - if (!contentDetected) { - const text = JSON.stringify(inputs); - item.push({ parts: [{ text }], role: "tool" } satisfies LlmContent); - } - return { item }; -}); - -export const functionDeclarationType = object({ - name: "string", - description: optional("string"), - parameters: optional(jsonSchema), -}); -export type FunctionDeclaration = ConvertBreadboardType< - typeof functionDeclarationType ->; - -export const functionSignatureFromBoardFunction = ({ - board, -}: { - board: Record; -}): { - function: FunctionDeclaration; - returns: Schema; - flags: FunctionCallFlags; - board: Record; -} => { - const b = board as GraphDescriptor; - const inputs = b.nodes.filter((node) => node.type === "input") || []; - const outputs = b.nodes.filter((node) => node.type === "output"); - if (outputs.length === 0) { - throw new Error("No outputs found"); - } - // For now, only support one input/output. - // TODO: Implement support for multiple inputs/outputs. - const inputSchema = (inputs[0]?.configuration?.schema || {}) as Schema; - const outputSchema = outputs[0].configuration?.schema as Schema; - if (!outputSchema) { - throw new Error("No output schema found"); - } - const properties: Record = {}; - const flags: FunctionCallFlags = {}; - for (const key in inputSchema.properties) { - const property = inputSchema.properties[key]; - const isObject = property.type === "object"; - const isArray = property.type === "array"; - const type = isObject || isArray ? "string" : property.type; - if (isObject && property.behavior?.includes("llm-content")) { - flags.inputLLMContent = key; - } else if ( - isArray && - (property.items as Schema)?.behavior?.includes("llm-content") - ) { - flags.inputLLMContentArray = key; - continue; - } - const description = property.description || property.title || "text"; - properties[key] = { type, description }; - } - if (flags.inputLLMContentArray) { - // Change the name of `board.args` parameter from `context` to the one - // specified by the flag. - if (flags.inputLLMContentArray !== "context") { - const c = b.args?.context; - if (c) { - b.args ??= {}; - b.args[flags.inputLLMContentArray] = c; - delete b.args.context; - } - } - } else { - // Remove the `context` parameter from the board args. - // There's no property that corresponds to it. - delete b.args?.context; - } - for (const key in outputSchema.properties) { - const property = outputSchema.properties[key]; - const isObject = property.type === "object"; - const isArray = property.type === "array"; - if (isObject && property.behavior?.includes("llm-content")) { - flags.outputLLMContent = key; - } else if ( - isArray && - (property.items as Schema)?.behavior?.includes("llm-content") - ) { - flags.outputLLMContentArray = key; - } - } - const name = b.title?.replace(/\W/g, "_") || "function"; - const description = b.description; - const parameters = - Object.entries(properties).length > 0 - ? { - type: "object", - properties, - } - : undefined; - - const f: FunctionDeclaration = { name, description }; - if (parameters) { - f.parameters = parameters; - } - return { - function: f, - returns: outputSchema, - flags, - board, - }; -}; - -export type FunctionSignatureItem = { - function: { name: string }; - boardURL: string; - flags: FunctionCallFlags; -}; - -export const functionDeclarationsFormatterFn = ({ - list, - routes, -}: { - list: FunctionSignatureItem[]; - routes: FunctionDeclaration[]; -}): { tools: JsonSerializable[]; urlMap: URLMap } => { - const tools: JsonSerializable[] = []; - const urlMap: URLMap = {}; - list.forEach((item) => { - tools.push(item.function); - const flags = item.flags; - urlMap[item.function.name] = { url: item.boardURL, flags }; - }); - routes.forEach((route) => { - tools.push(route); - urlMap[route.name] = { url: "", flags: {} }; - }); - return { tools, urlMap }; -}; - -export const toolResponseType = object({ item: array(llmContentType) }); -export type ToolResponse = ConvertBreadboardType; - -export const responseCollatorFunction = ({ - response, - context, - generated, -}: { - response: ToolResponse[]; - context?: LlmContent[]; - generated: LlmContent; -}): Record => { - const result = Object.fromEntries( - response.map((item, i) => [`context-${i + 2}`, item.item]) - ); - if (context) { - result["context-0"] = context; - } - result["context-1"] = [generated]; - return result; -}; diff --git a/packages/agent-kit/src/generate-kit-manifest.ts b/packages/agent-kit/src/generate-kit-manifest.ts deleted file mode 100644 index 9aa319905f3..00000000000 --- a/packages/agent-kit/src/generate-kit-manifest.ts +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import path from "path"; -import { fileURLToPath } from "url"; - -import { KitManifest } from "@google-labs/breadboard"; - -import worker from "./boards/worker.js"; -import human from "./boards/human.js"; -import repeater from "./boards/repeater.js"; -import structuredWorker from "./boards/structured-worker.js"; -import { writeFile } from "fs/promises"; -import specialist from "./boards/specialist.js"; -import looper from "./boards/looper.js"; -import joiner from "./boards/joiner.js"; -import { serialize } from "@breadboard-ai/build"; -import content from "./boards/content.js"; - -const MANIFEST_NAME = "agent.kit.json"; - -const MODULE_DIR = path.dirname(fileURLToPath(import.meta.url)); -const ROOT_DIR = path.join(MODULE_DIR, ".."); -const BOARDS_DIR = path.join(ROOT_DIR, "boards"); -const MANIFEST_PATH = path.join(ROOT_DIR, MANIFEST_NAME); - -const manifest: KitManifest = { - title: "Agent Kit", - description: "A collection of nodes for building Agent-like experiences.", - version: "0.0.1", - url: `https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/${MANIFEST_NAME}`, - nodes: { - human: serialize(human), - repeater: serialize(repeater), - structuredWorker: serialize(structuredWorker), - specialist: serialize(specialist), - worker: serialize(worker), - looper: serialize(looper), - joiner: serialize(joiner), - content: serialize(content), - }, -}; - -const generate = async () => { - // Write individual nodes to the file system - const nodes = Object.entries(manifest.nodes); - await Promise.all( - nodes.map(async ([name, node]) => { - if (node.metadata?.deprecated) return; - const nodePath = path.join(BOARDS_DIR, `${name}.bgl.json`); - const json = JSON.stringify(node, null, 2); - return writeFile(nodePath, json); - }) - ); - - // Write the manifest to the file system - const json = JSON.stringify(manifest, null, 2); - return writeFile(MANIFEST_PATH, json); -}; - -await generate(); diff --git a/packages/agent-kit/src/index.ts b/packages/agent-kit/src/index.ts deleted file mode 100644 index e3eda8ea7fb..00000000000 --- a/packages/agent-kit/src/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { kit } from "@breadboard-ai/build"; -import human from "./boards/human.js"; -import joiner from "./boards/joiner.js"; -import looper from "./boards/looper.js"; -import repeater from "./boards/repeater.js"; -import specialist from "./boards/specialist.js"; -import structuredWorker from "./boards/structured-worker.js"; -import worker from "./boards/worker.js"; -import content from "./boards/content.js"; - -const agentKit = await kit({ - title: "Agent Kit", - description: "A collection of nodes for building Agent-like experiences.", - version: "0.0.1", - url: "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/graphs/kit.json", - components: { - content, - human, - joiner, - looper, - repeater, - specialist, - structuredWorker, - worker, - }, -}); - -export default agentKit; -export const agents = await agentKit.legacy(); diff --git a/packages/agent-kit/src/js-components/substitute.ts b/packages/agent-kit/src/js-components/substitute.ts deleted file mode 100644 index cc6af8b2063..00000000000 --- a/packages/agent-kit/src/js-components/substitute.ts +++ /dev/null @@ -1,235 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { Context, LlmContent } from "../context.js"; -import type { FunctionDeclaration } from "../function-calling.js"; -import type { - Operation, - ParamInfo, - ParamLocationMap, - TemplatePart, -} from "../templating.js"; -import { - isEmptyContent, - isLLMContent, - isLLMContentArray, - toId, - toTitle, - unique, -} from "../util.js"; - -export type Inputs = { - in?: Context[]; - persona?: LlmContent; - task?: LlmContent; - // TODO(aomarks) The following should be uncommented, but there's a typing - // issue in the Build API that makes this not work. Needs investigation. - // Doesn't make a huge difference, but will require some casting e.g. in - // tests. - // - // [param: string]: unknown; -}; - -export type Outputs = { - in: Context[]; - persona: LlmContent | string; - task: LlmContent | string; - outs: FunctionDeclaration[]; -}; - -/** - * Part of the "Specialist" v2 component that does the parameter - * substitution. - */ -export function run(inputParams: Inputs): Outputs { - const { in: context = [], persona, task, ...inputs } = inputParams; - const personaParams = findParams(persona); - const taskParams = findParams(task); - const params = mergeParams(personaParams, taskParams); - - // Make sure that all params are present in the values and collect - // them into a single object. - const values = collectValues(params, inputs); - - if (context.length === 0 && !task) { - throw new Error( - "Both conversation Context and Task are empty. Specify at least one of them." - ); - } - - return { - in: context, - persona: subContent(persona, values), - task: subContent(task, values), - outs: collectOuts(personaParams, taskParams), - }; -} - -function collectOuts(...paramsList: ParamInfo[][]) { - const functionNames = unique( - paramsList - .flat() - .map((param) => { - const { name, op } = param; - if (op !== "out") return null; - return name; - }) - .filter(Boolean) - ) as string[]; - return functionNames.map((name) => { - const toolName = `TOOL_${name.toLocaleUpperCase()}`; - return { - name: toolName, - description: `Call this function when asked to invoke the "${toolName}" tool.`, - } satisfies FunctionDeclaration; - }); -} - -function findParams(content: LlmContent | undefined): ParamInfo[] { - const parts = content?.parts; - if (!parts) return []; - const results = parts.flatMap((part) => { - if (!("text" in part)) return [] as ParamInfo[]; - const matches = part.text.matchAll( - /{{\s*(?[\w-]+)(?:\s*\|\s*(?[\w-]*)(?::\s*"(?[\w-]+)")?)?\s*}}/g - ); - return unique(Array.from(matches)) - .map((match) => { - const name = match.groups?.name || ""; - const op = match.groups?.op || ""; - const arg = match.groups?.arg || ""; - if (!name) return null; - return { name, op, arg, locations: [{ part, parts }] } as ParamInfo; - }) - .filter(Boolean); - }) as ParamInfo[]; - return results; -} - -function mergeParams(...paramList: ParamInfo[][]) { - const result = paramList.reduce((acc, params) => { - for (const param of params) { - if (param.op && param.op !== "in") { - continue; - } - const { name, locations } = param; - const existing = acc[name]; - if (existing) { - existing.push(...locations); - } else { - acc[name] = locations; - } - } - return acc; - }, {} as ParamLocationMap); - return result; -} - -function subContent( - content: LlmContent | undefined, - values: Record -): LlmContent | string { - // If this is an array, optimistically presume this is an LLM Content array. - // Take the last item and use it as the content. - if (Array.isArray(content)) { - content = content.at(-1); - } - if (isEmptyContent(content)) return ""; - return { - role: content.role || "user", - parts: mergeTextParts( - splitToTemplateParts(content).flatMap((part) => { - if ("param" in part) { - const { op = "in" } = part; - if (op === "in") { - const value = values[part.param]; - if (typeof value === "string") { - return { text: value }; - } else if (isLLMContent(value)) { - return value.parts; - } else if (isLLMContentArray(value)) { - const last = value.at(-1); - return last ? last.parts : []; - } else { - return { text: JSON.stringify(value) }; - } - } else { - return { text: `"TOOL_${part.param.toLocaleUpperCase()}"` }; - } - } else { - return part; - } - }) - ), - }; -} - -function mergeTextParts(parts: TemplatePart[]) { - const merged = []; - for (const part of parts) { - if ("text" in part) { - const last = merged[merged.length - 1]; - if (last && "text" in last) { - last.text += part.text; - } else { - merged.push(part); - } - } else { - merged.push(part); - } - } - return merged as LlmContent["parts"]; -} - -/** - * Takes an LLM Content and splits it further into parts where - * each {{param}} substitution is a separate part. - */ -function splitToTemplateParts(content: LlmContent): TemplatePart[] { - const parts: TemplatePart[] = []; - for (const part of content.parts) { - if (!("text" in part)) { - parts.push(part); - continue; - } - const matches = part.text.matchAll( - /{{\s*(?[\w-]+)(?:\s*\|\s*(?[\w-]*)(?::\s*"(?[\w-]+)")?)?\s*}}/g - ); - let start = 0; - for (const match of matches) { - const name = match.groups?.name || ""; - const op = match.groups?.op as Operation; - const arg = match.groups?.arg; - const end = match.index; - if (end > start) { - parts.push({ text: part.text.slice(start, end) }); - } - parts.push({ param: name, op, arg }); - start = end + match[0].length; - } - if (start < part.text.length) { - parts.push({ text: part.text.slice(start) }); - } - } - return parts; -} - -function collectValues( - params: ParamLocationMap, - inputs: Record -) { - const values: Record = {}; - for (const param in params) { - const id = toId(param); - const value = inputs[id]; - if (!value) { - const title = toTitle(param); - throw new Error(`Missing required parameter: ${title}`); - } - values[param] = value; - } - return values; -} diff --git a/packages/agent-kit/src/samples/poet.ts b/packages/agent-kit/src/samples/poet.ts deleted file mode 100644 index 7463c9598bf..00000000000 --- a/packages/agent-kit/src/samples/poet.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { array, board, input } from "@breadboard-ai/build"; -import agents from "@google-labs/agent-kit"; -import { contextType } from "../context.js"; - -const context = input({ - title: "Poem topic", - type: array(contextType), - examples: [[{ role: "user", parts: [{ text: "the universe within us" }] }]], -}); - -const worker = agents.worker({ - $id: "writePoetry", - instruction: `You are a brilliant poet who specializes in two-line rhyming poems. - Given any topic, you can quickly whip up a two-line rhyming poem about it. - Ready?`, - context, -}); - -export default board({ - title: "Two-line Rhyming Poet", - description: "A simple example of using of the Worker node", - inputs: { context }, - outputs: { context: worker.outputs.context }, -}); diff --git a/packages/agent-kit/src/samples/summarizer.ts b/packages/agent-kit/src/samples/summarizer.ts deleted file mode 100644 index 1ca0265e558..00000000000 --- a/packages/agent-kit/src/samples/summarizer.ts +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { board, input, string, type Value } from "@breadboard-ai/build"; -import { type JsonSerializable } from "@breadboard-ai/build/internal/type-system/type.js"; -import { type Context } from "../context.js"; -import agents from "../index.js"; - -const superDenseText = - "In one aspect, a system is described to include computer data servers each storing and operable to serve a partition of a collection of data. The respective partitions together constitute the collection of data and each respective partition is less than the collection of data. This system also includes a processing server operable to obtain data from the data servers and to use the obtained data to process an input and to produce an output. The system can be implemented to include one or more replica data servers for each of the data servers. In one implementation, the collection of data is data for a language model for a target language. The language model includes n grams in the target language and statistical data for each of the n grams. The n grams can include N-grams with N greater than 3. The processing server is a translation server operable to translate a text in a source language in the input into the target language using the obtained data from the language model. The processing server can be implemented in various configurations, e.g., a speech recognition server operable to convert a human speech in the target language in the input into a text in the target language using the obtained data from the language model, a spelling correction server operable to correct a spelling of a word in the target language in the input using the obtained data from the language model, or an optical character recognition server operable to recognize text in a received document image in the input using the obtained data from the language model."; - -const paragraph = input({ - title: "Text to summarize", - type: string({ format: "multiline" }), - examples: [superDenseText], -}); - -const summarize = agents.worker({ - $id: "summarize", - // TODO(aomarks) We want worker to allow string OR object, but the visual - // editor doesn't support anyOf, so we can't until it does. The code actually - // does support string, so just cast. - context: paragraph as Value as Value, - instruction: - "You are a genius legal expert. You specialize in carefully reading the dense paragraphs of patent application texts and summarizing them in a few simple sentences that most people can understand.", -}); - -const critique = agents.worker({ - $id: "critique", - context: summarize.outputs.context, - instruction: - "Now, put your critiquing hat on. Compare the summary with the original text and identify three areas of improvement. What is missing? What could be better phrased? What could be removed?", -}); - -const improve = agents.worker({ - $id: "improve", - context: critique.outputs.context, - instruction: - "Use the identified areas of improvement to come up with an even better summary than the one before. Use your best elite skills as the writer.", -}); - -const abbreviate = agents.worker({ - $id: "abbreviate", - context: improve.outputs.context, - instruction: - "Make the improved summary even shorter, while keeping the most important details. Remove any headings or other formatting that is not needed. Make it just a simple paragraph of text.", -}); - -export default board({ - title: "Dense text summarizer", - description: - "Turns particularly dense text passages into easy-to-understand summaries", - version: "0.0.1", - inputs: { paragraph }, - outputs: { - context: abbreviate.outputs.context, - text: abbreviate.outputs.text, - }, -}); diff --git a/packages/agent-kit/src/templating.ts b/packages/agent-kit/src/templating.ts deleted file mode 100644 index 6dcd6e8b612..00000000000 --- a/packages/agent-kit/src/templating.ts +++ /dev/null @@ -1,547 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Schema } from "@google-labs/breadboard"; -import { Context, LlmContent } from "./context.js"; - -export { describeSpecialist, content, describeContent }; - -type Location = { - part: LlmContent["parts"][0]; - parts: LlmContent["parts"]; -}; - -export type ParamLocationMap = Record; - -export type Operation = "in" | "out"; - -export type ParamInfo = { - name: string; - locations: Location[]; - op?: Operation; - arg?: string; -}; - -export type TemplatePart = - | LlmContent["parts"][0] - | { param: string; op?: Operation; arg?: string }; - -type SpecialistDescriberInputs = { - $inputSchema: Schema; - $outputSchema: Schema; - persona?: LlmContent; - task?: LlmContent; -}; - -type ContentInputs = { - template: LlmContent; - context?: LlmContent[]; - [param: string]: unknown; -}; - -type DescribeContentInputs = { - template?: LlmContent; -}; - -/** - * The describer for the "Specialist" v2 component. - */ -function describeSpecialist(inputs: unknown) { - const { $inputSchema, $outputSchema, persona, task } = - inputs as SpecialistDescriberInputs; - - const inputSchema: Schema = { - type: "object", - additionalProperties: false, - properties: { - ...$inputSchema.properties, - in: { - title: "Context in", - description: "Incoming conversation context", - type: "array", - items: { - type: "object", - behavior: ["llm-content"], - }, - examples: [], - }, - task: { - title: "Task", - description: - "(Optional) Provide a specific task with clear instructions for the worker to complete using the conversation context. Use mustache-style {{params}} to add parameters.", - type: "object", - default: '{"role":"user","parts":[{"text":""}]}', - behavior: ["llm-content", "config"], - examples: [], - }, - persona: { - type: "object", - behavior: ["llm-content", "config"], - title: "Persona", - description: - "Describe the worker's skills, capabilities, mindset, and thinking process. Use mustache-style {{params}} to add parameters.", - default: '{"role":"user","parts":[{"text":""}]}', - examples: [], - }, - }, - required: [], - }; - - const all = [ - ...collectParams(textFromLLMContent(persona)), - ...collectParams(textFromLLMContent(task)), - ]; - const params: string[] = []; - const outs: string[] = []; - - for (const param of all) { - const { op = "in" } = param; - if (op === "in") { - params.push(param.name); - } else { - outs.push(param.name); - } - } - - const inputProps = Object.fromEntries( - unique(params).map((param) => [ - toId(param), - { - title: toTitle(param), - description: `The value to substitute for the parameter "${param}"`, - type: "string", - }, - ]) - ); - - const outputProps = Object.fromEntries( - unique(outs).map((param) => [ - toId(`TOOL_${param.toLocaleUpperCase()}`), - { - title: toTitle(param), - description: `The output chosen when the "${param}" tool is invoked`, - type: "string", - }, - ]) - ); - - const required = params.map(toId); - - return mergeSchemas(inputSchema, $outputSchema, inputProps, outputProps); - - function mergeSchemas( - inputSchema: Schema, - outputSchema: Schema, - properties: Record, - outputProps: Record - ) { - return { - inputSchema: { - ...inputSchema, - properties: { - ...inputSchema.properties, - ...properties, - }, - required: [...(inputSchema.required || []), ...required], - }, - outputSchema: { - ...outputSchema, - properties: { - ...outputSchema.properties, - ...outputProps, - }, - }, - }; - } - - function toId(param: string) { - return `p-${param}`; - } - - function toTitle(id: string) { - const spaced = id?.replace(/[_-]/g, " "); - return ( - (spaced?.at(0)?.toUpperCase() ?? "") + - (spaced?.slice(1)?.toLowerCase() ?? "") - ); - } - - function textFromLLMContent(content: LlmContent | undefined) { - return ( - content?.parts - .map((item) => { - return "text" in item ? item.text : ""; - }) - .join("\n") || "" - ); - } - - function unique(params: T[]): T[] { - return Array.from(new Set(params)); - } - - function collectParams(text: string): ParamInfo[] { - if (!text) return []; - const matches = text.matchAll( - /{{\s*(?[\w-]+)(?:\s*\|\s*(?[\w-]*)(?::\s*"(?[\w-]+)")?)?\s*}}/g - ); - return Array.from(matches).map((match) => { - const name = match.groups?.name || ""; - const op = match.groups?.op; - const arg = match.groups?.arg; - return { name, op, arg, locations: [] } as ParamInfo; - }); - } -} - -/** - * The guts of the "Content" component. - */ -function content(starInputs: unknown) { - const { template, context, ...inputs } = starInputs as ContentInputs; - const params = mergeParams(findParams(template)); - const values = collectValues(params, inputs); - - return { - context: prependContext(context, subContent(template, values)), - }; - - function prependContext( - context: LlmContent[] | undefined, - c: LlmContent | string - ): LlmContent[] { - const content = (isEmptyContent(c) ? [] : [c]) as LlmContent[]; - if (!context) return [...content] as LlmContent[]; - if (isLLMContentArray(context)) { - // If the last item in the context has a user rule, - // merge the new content with it instead of creating a new item. - const last = context.at(-1); - if (last && last.role === "user") { - return [ - ...context.slice(0, -1), - { - role: "user", - parts: [ - ...last.parts, - ...((content.at(0) as LlmContent)?.parts || []), - ], - }, - ]; - } - return [...context, ...content] as LlmContent[]; - } - return content; - } - - function isEmptyContent(content: LlmContent | string | undefined) { - if (!content) return true; - if (typeof content === "string") return true; - if (!content.parts?.length) return true; - if (content.parts.length > 1) return false; - const part = content.parts[0]; - if (!("text" in part)) return true; - if (part.text.trim() === "") return true; - return false; - } - - function subContent( - content: LlmContent | undefined, - values: Record - ): LlmContent | string { - // If this is an array, optimistically presume this is an LLM Content array. - // Take the last item and use it as the content. - if (Array.isArray(content)) { - content = content.at(-1); - } - if (!content) return ""; - return { - role: content.role || "user", - parts: mergeTextParts( - splitToTemplateParts(content).flatMap((part) => { - if ("param" in part) { - const value = values[part.param]; - if (typeof value === "string") { - return { text: value }; - } else if (isLLMContent(value)) { - return value.parts; - } else if (isLLMContentArray(value)) { - const last = getLastNonMetadata(value); - return last ? last.parts : []; - } else { - return { text: JSON.stringify(value) }; - } - } else { - return part; - } - }) - ), - }; - } - - function getLastNonMetadata(content: Context[]): LlmContent | null { - for (let i = content.length - 1; i >= 0; i--) { - if (content[i].role !== "$metadata") { - return content[i] as LlmContent; - } - } - return null; - } - - function findParams(content: LlmContent | undefined): ParamInfo[] { - const parts = content?.parts; - if (!parts) return []; - const results = parts.flatMap((part) => { - if (!("text" in part)) return []; - const matches = part.text.matchAll( - /{{\s*(?[\w-]+)(?:\s*\|\s*(?[\w-]*)(?::\s*"(?[\w-]+)")?)?\s*}}/g - ); - return unique(Array.from(matches)) - .map((match) => { - const name = match.groups?.name || ""; - if (!name) return null; - return { name, locations: [{ part, parts }] }; - }) - .filter(Boolean); - }) as unknown as ParamInfo[]; - return results; - } - - function mergeParams(...paramList: ParamInfo[][]) { - return paramList.reduce((acc, params) => { - for (const param of params) { - const { name, locations } = param; - const existing = acc[name]; - if (existing) { - existing.push(...locations); - } else { - acc[name] = locations; - } - } - return acc; - }, {} as ParamLocationMap); - } - - function unique(params: T[]): T[] { - return Array.from(new Set(params)); - } - - function mergeTextParts(parts: TemplatePart[]) { - const merged = []; - for (const part of parts) { - if ("text" in part) { - const last = merged[merged.length - 1]; - if (last && "text" in last) { - last.text += part.text; - } else { - merged.push(part); - } - } else { - merged.push(part); - } - } - return merged as LlmContent["parts"]; - } - - function toId(param: string) { - return `p-${param}`; - } - - function toTitle(id: string) { - const spaced = id?.replace(/[_-]/g, " "); - return ( - (spaced?.at(0)?.toUpperCase() ?? "") + - (spaced?.slice(1)?.toLowerCase() ?? "") - ); - } - - /** - * Takes an LLM Content and splits it further into parts where - * each {{param}} substitution is a separate part. - */ - function splitToTemplateParts(content: LlmContent): TemplatePart[] { - const parts = []; - for (const part of content.parts) { - if (!("text" in part)) { - parts.push(part); - continue; - } - const matches = part.text.matchAll( - /{{\s*(?[\w-]+)(?:\s*\|\s*(?[\w-]*)(?::\s*"(?[\w-]+)")?)?\s*}}/g - ); - let start = 0; - for (const match of matches) { - const name = match.groups?.name || ""; - const end = match.index; - if (end > start) { - parts.push({ text: part.text.slice(start, end) }); - } - parts.push({ param: name }); - start = end + match[0].length; - } - if (start < part.text.length) { - parts.push({ text: part.text.slice(start) }); - } - } - return parts; - } - - function collectValues( - params: ParamLocationMap, - inputs: Record - ) { - const values: Record = {}; - for (const param in params) { - const id = toId(param); - const value = inputs[id]; - if (!value) { - const title = toTitle(param); - throw new Error(`Missing required parameter: ${title}`); - } - values[param] = value; - } - return values; - } - - /** - * Copied from @google-labs/breadboard - */ - function isLLMContent(nodeValue: unknown): nodeValue is LlmContent { - if (typeof nodeValue !== "object" || !nodeValue) return false; - if (nodeValue === null || nodeValue === undefined) return false; - - if ("role" in nodeValue && nodeValue.role === "$metadata") { - return true; - } - - return "parts" in nodeValue && Array.isArray(nodeValue.parts); - } - - function isLLMContentArray(nodeValue: unknown): nodeValue is LlmContent[] { - if (!Array.isArray(nodeValue)) return false; - if (nodeValue.length === 0) return true; - return isLLMContent(nodeValue.at(-1)); - } -} - -/** - * The describer for the "Content" component. - */ -function describeContent(inputs: unknown) { - const { template } = inputs as DescribeContentInputs; - const params = unique([...collectParams(textFromLLMContent(template))]); - - const props = Object.fromEntries( - params.map((param) => [ - toId(param), - { - title: toTitle(param), - description: `The value to substitute for the parameter "${param}"`, - type: "string", - }, - ]) - ); - - const $inputSchema: Schema = { - properties: { - context: { - type: "array", - title: "Context in", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - description: "The optional incoming conversation context", - }, - template: { - type: "object", - title: "Template", - examples: [], - behavior: ["llm-content", "config"], - default: "null", - description: - "(Optional) Content that will initialize a new conversation contenxt or be appended to the existing one. Use mustache-style {{params}} to add parameters.", - }, - }, - type: "object", - required: [], - }; - - const $outputSchema: Schema = { - type: "object", - properties: { - context: { - type: "array", - title: "Context out", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - description: - "The resulting context, created from the template and parameters.", - }, - }, - required: [], - }; - - const required = params.map(toId); - - return mergeSchemas($inputSchema, $outputSchema, props); - - function mergeSchemas( - inputSchema: Schema, - outputSchema: Schema, - properties: Record - ) { - return { - inputSchema: { - ...inputSchema, - properties: { - ...inputSchema.properties, - ...properties, - }, - required: [...(inputSchema.required || []), ...required], - }, - outputSchema: outputSchema, - }; - } - - function toId(param: string) { - return `p-${param}`; - } - - function toTitle(id: string) { - const spaced = id?.replace(/[_-]/g, " "); - return ( - (spaced?.at(0)?.toUpperCase() ?? "") + - (spaced?.slice(1)?.toLowerCase() ?? "") - ); - } - - function textFromLLMContent(content: LlmContent | undefined) { - return ( - content?.parts - .map((item) => { - return "text" in item ? item.text : ""; - }) - .join("\n") || "" - ); - } - - function unique(params: T[]): T[] { - return Array.from(new Set(params)); - } - - function collectParams(text: string) { - if (!text) return []; - const matches = text.matchAll( - /{{\s*(?[\w-]+)(?:\s*\|\s*(?[\w-]*)(?::\s*"(?[\w-]+)")?)?\s*}}/g - ); - return Array.from(matches).map((match) => match.groups?.name || ""); - } -} diff --git a/packages/agent-kit/src/util.ts b/packages/agent-kit/src/util.ts deleted file mode 100644 index cc905f3802d..00000000000 --- a/packages/agent-kit/src/util.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { LlmContent } from "./context.js"; - -export function unique(params: T[]): T[] { - return Array.from(new Set(params)); -} - -export function toId(param: string) { - return `p-${param}`; -} - -export function isEmptyContent( - content: LlmContent | string | undefined -): content is undefined { - if (!content) return true; - if (typeof content === "string") return true; - if (!content.parts?.length) return true; - if (content.parts.length > 1) return false; - const part = content.parts[0]; - if (!("text" in part)) return true; - if (part.text.trim() === "") return true; - return false; -} - -/** - * Copied from @google-labs/breadboard - */ -export function isLLMContent(nodeValue: unknown): nodeValue is LlmContent { - if (typeof nodeValue !== "object" || !nodeValue) return false; - if (nodeValue === null || nodeValue === undefined) return false; - - if ("role" in nodeValue && nodeValue.role === "$metadata") { - return true; - } - - return "parts" in nodeValue && Array.isArray(nodeValue.parts); -} - -export function isLLMContentArray(nodeValue: unknown): nodeValue is LlmContent[] { - if (!Array.isArray(nodeValue)) return false; - if (nodeValue.length === 0) return true; - return isLLMContent(nodeValue.at(-1)); -} - -export function toTitle(id: string) { - const spaced = id?.replace(/[_-]/g, " "); - return ( - (spaced?.at(0)?.toUpperCase() ?? "") + - (spaced?.slice(1)?.toLowerCase() ?? "") - ); -} diff --git a/packages/agent-kit/tests/boards/context-arg.json b/packages/agent-kit/tests/boards/context-arg.json deleted file mode 100644 index 3c114284b9c..00000000000 --- a/packages/agent-kit/tests/boards/context-arg.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "title": "Picture Story Teller", - "version": "0.0.1", - "edges": [ - { - "from": "specialist-6c4f145f", - "to": "output", - "out": "out", - "in": "text" - }, - { - "from": "input-2ac00dd6", - "to": "specialist-6c4f145f", - "out": "property-1", - "in": "in" - } - ], - "nodes": [ - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "array", - "title": "Story", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - } - } - }, - "required": [] - } - }, - "metadata": { - "visual": { - "x": 258, - "y": -59 - } - } - }, - { - "id": "specialist-6c4f145f", - "type": "specialist", - "metadata": { - "visual": { - "x": -7, - "y": -62.999999999999986 - }, - "title": "Story Teller", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a wise story teller. Given any picture, you can immediately spin up a wonderful fable that uses the contents of a picture as inspiration. This fable is for kindergarten kids and always has a good teachable moral." - } - ] - } - } - }, - { - "id": "input-2ac00dd6", - "type": "input", - "metadata": { - "visual": { - "x": -204.00000000000003, - "y": -76 - }, - "title": "Context", - "logLevel": "debug" - }, - "configuration": { - "schema": { - "properties": { - "property-1": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - } - } - }, - "type": "object", - "required": [] - } - } - } - ], - "args": { - "context": "foo" - } -} diff --git a/packages/agent-kit/tests/boards/holiday-researcher.json b/packages/agent-kit/tests/boards/holiday-researcher.json deleted file mode 100644 index dbe9c7cabf3..00000000000 --- a/packages/agent-kit/tests/boards/holiday-researcher.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "title": "Holiday Researcher", - "version": "0.0.1", - "edges": [ - { - "from": "input", - "to": "specialist-8205dc7e", - "in": "in", - "out": "text" - }, - { - "from": "specialist-8205dc7e", - "to": "output", - "out": "out", - "in": "text" - } - ], - "nodes": [ - { - "id": "specialist-8205dc7e", - "type": "specialist", - "metadata": { - "visual": { - "x": 14, - "y": -70 - }, - "title": "Researcher", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are an expert researcher of holiday dates." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Given a request, get the next public holiday for the country specified." - } - ] - }, - "tools": [ - "http://localhost:5173/graphs/nager.date/next-public-holiday.json" - ] - } - }, - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "object", - "title": "Country", - "examples": [], - "behavior": ["llm-content"], - "default": "null", - "description": "The name of the country whose holidays to research" - } - }, - "required": [] - } - }, - "metadata": { - "visual": { - "x": -147, - "y": 50 - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "object", - "title": "text", - "behavior": ["llm-content"] - } - } - } - }, - "metadata": { - "visual": { - "x": 366, - "y": -124 - } - } - } - ] -} diff --git a/packages/agent-kit/tests/boards/llm-content-array.json b/packages/agent-kit/tests/boards/llm-content-array.json deleted file mode 100644 index 94d20918b7e..00000000000 --- a/packages/agent-kit/tests/boards/llm-content-array.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "title": "Blank board", - "version": "0.0.1", - "edges": [ - { - "from": "input", - "out": "text", - "to": "output", - "in": "text" - } - ], - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - } - } - }, - "required": [] - } - }, - "metadata": { - "visual": { - "x": 0, - "y": 0 - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - } - } - }, - "required": [] - } - }, - "metadata": { - "visual": { - "x": 193, - "y": 0 - } - } - } - ] -} diff --git a/packages/agent-kit/tests/boards/next-public-holiday.json b/packages/agent-kit/tests/boards/next-public-holiday.json deleted file mode 100644 index 739ac964dd1..00000000000 --- a/packages/agent-kit/tests/boards/next-public-holiday.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "title": "Nager Date Next Public Holiday", - "description": "Get the next public holiday for a given country", - "version": "0.0.1", - "edges": [ - { - "from": "fetch-0", - "to": "output-0", - "out": "response", - "in": "holidays" - }, - { - "from": "input-0", - "to": "urlTemplate-0", - "out": "countryCode", - "in": "countryCode" - }, - { - "from": "urlTemplate-0", - "to": "fetch-0", - "out": "url", - "in": "url" - } - ], - "nodes": [ - { - "id": "input-0", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "countryCode": { - "type": "string", - "title": "Country Code", - "description": "Two-letter country code" - } - }, - "required": ["countryCode"] - } - } - }, - { - "id": "output-0", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "holidays": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "Holidays", - "description": "A list of public holidays for the given country" - } - }, - "required": ["holidays"] - } - } - }, - { - "id": "fetch-0", - "type": "fetch", - "configuration": { - "headers": { - "Content-Type": "application/json" - }, - "method": "GET" - }, - "metadata": { - "title": "Call API", - "description": "Calling the Nager Date API to get the next public holiday for the given country" - } - }, - { - "id": "urlTemplate-0", - "type": "urlTemplate", - "configuration": { - "template": "https://date.nager.at/api/v3/NextPublicHolidays/{countryCode}" - }, - "metadata": { - "title": "URL Template", - "description": "Creating the API URL" - } - } - ] -} diff --git a/packages/agent-kit/tests/boards/no-descriptions.json b/packages/agent-kit/tests/boards/no-descriptions.json deleted file mode 100644 index 58c3232b587..00000000000 --- a/packages/agent-kit/tests/boards/no-descriptions.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "title": "Holiday Researcher", - "version": "0.0.1", - "edges": [ - { - "from": "input", - "to": "specialist-8205dc7e", - "in": "in", - "out": "text" - }, - { - "from": "specialist-8205dc7e", - "to": "output", - "out": "out", - "in": "text" - } - ], - "nodes": [ - { - "id": "specialist-8205dc7e", - "type": "specialist", - "metadata": { - "visual": { - "x": 14, - "y": -70 - }, - "title": "Researcher", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are an expert researcher of holiday dates." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Given a request, get the next public holiday for the country specified." - } - ] - }, - "tools": [ - "http://localhost:5173/graphs/nager.date/next-public-holiday.json" - ] - } - }, - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "object", - "title": "text", - "examples": [], - "behavior": ["llm-content"] - } - }, - "required": [] - } - }, - "metadata": { - "visual": { - "x": -151, - "y": 115 - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "text" - } - } - } - }, - "metadata": { - "visual": { - "x": 366, - "y": -124 - } - } - } - ] -} diff --git a/packages/agent-kit/tests/boards/today.json b/packages/agent-kit/tests/boards/today.json deleted file mode 100644 index 4e34c6cfebb..00000000000 --- a/packages/agent-kit/tests/boards/today.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "title": "Get Today", - "description": "Return today's date", - "version": "0.0.1", - "metadata": { - "tags": ["tool", "published"], - "comments": [] - }, - "edges": [ - { - "from": "runJavascript-94b48cbd", - "to": "output", - "in": "today", - "out": "result" - } - ], - "nodes": [ - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "today": { - "type": "string", - "title": "Today", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 138, - "y": 95, - "collapsed": false - } - } - }, - { - "id": "runJavascript-94b48cbd", - "type": "runJavascript", - "metadata": { - "visual": { - "x": -99, - "y": 16, - "collapsed": false - }, - "title": "Today", - "logLevel": "debug" - }, - "configuration": { - "name": "run", - "code": "function run() {\n return `Today is ${new Date().toString()}`;\n}" - } - } - ] -} diff --git a/packages/agent-kit/tests/combine-contexts.ts b/packages/agent-kit/tests/combine-contexts.ts deleted file mode 100644 index 5d313829bc7..00000000000 --- a/packages/agent-kit/tests/combine-contexts.ts +++ /dev/null @@ -1,268 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { - Context, - LlmContent, - SplitMarkerData, - SplitMetadata, - combineContextsFunction, -} from "../src/context.js"; -import { deepStrictEqual, ok } from "node:assert"; - -const split = (type: SplitMarkerData["type"], id: string): Context => { - return { role: "$metadata", type: "split", data: { id, type } }; -}; - -const text = (text: string): Context => { - return { parts: [{ text }] }; -}; - -describe("combineContexts", () => { - test("works fine when `merge` isn't specified", () => { - const a1 = text("Before"); - const a2 = text("Hello"); - const b1 = text("In a"); - const b2 = text("world"); - const result = combineContextsFunction({ - contextA: [a1, a2] satisfies Context[], - contextB: [b1, b2] satisfies Context[], - }) as { context: Context[] }; - - // Fish out the marker - const marker = (result?.context[0] as SplitMetadata)?.data?.id; - ok(marker, "Marker is missing"); - - deepStrictEqual(result, { - context: [ - split("start", marker), - a1, - a2, - split("next", marker), - b1, - b2, - split("end", marker), - ], - }); - }); - - test("works fine with split markers in the context", () => { - const common = text("Common"); - const a1 = text("Before"); - const a2 = text("Hello"); - const b1 = text("In a"); - const b2 = text("world"); - const result = combineContextsFunction({ - contextA: [common, split("start", "1"), a1, a2] satisfies Context[], - contextB: [common, split("start", "1"), b1, b2] satisfies Context[], - }) as { context: Context[] }; - - deepStrictEqual(result, { - context: [ - common, - split("start", "1"), - a1, - a2, - split("next", "1"), - b1, - b2, - split("end", "1"), - ], - }); - }); - - test("handles context ending with a split marker", () => { - const a1 = text("Before"); - const a2 = text("Hello"); - const result = combineContextsFunction({ - contextA: [a1, split("start", "1")] satisfies Context[], - contextB: [a1, split("start", "1"), a2] satisfies Context[], - }) as { context: Context[] }; - - deepStrictEqual(result, { - context: [a1, split("start", "1"), a2, split("end", "1")], - }); - }); - - test("ignores split markers when some context are missing them", () => { - const a1 = text("Before"); - const a2 = text("Hello"); - const b1 = text("In a"); - const b2 = text("world"); - const result = combineContextsFunction({ - contextA: [a1, a2] satisfies Context[], - contextB: [b1, b2, split("start", "1")] satisfies Context[], - }) as { context: Context[] }; - - deepStrictEqual(result, { - context: [a1, a2, b1, b2, split("start", "1")], - }); - }); - - test("Handles resolved and nested split markers", () => { - const a1 = text("a1"); - const a2 = text("a2"); - const a3 = text("a3"); - const b3 = text("b3"); - { - const result = combineContextsFunction({ - contextA: [ - a1, - split("start", "1"), - a2, - split("end", "1"), - split("start", "2"), - a3, - ] satisfies Context[], - contextB: [ - a1, - split("start", "1"), - a2, - split("end", "1"), - split("start", "2"), - b3, - ] satisfies Context[], - }) as { context: Context[] }; - - deepStrictEqual(result, { - context: [ - a1, - split("start", "1"), - a2, - split("end", "1"), - split("start", "2"), - a3, - split("next", "2"), - b3, - split("end", "2"), - ], - }); - } - { - const result = combineContextsFunction({ - contextA: [ - a1, - split("start", "1"), - a2, - split("end", "1"), - a3, - ] satisfies Context[], - contextB: [ - a1, - split("start", "1"), - a2, - split("end", "1"), - b3, - ] satisfies Context[], - }) as { context: Context[] }; - - // Fish out the split marker. - const marker = (result?.context[0] as SplitMetadata)?.data?.id; - - deepStrictEqual(result, { - context: [ - split("start", marker), - a1, - split("start", "1"), - a2, - split("end", "1"), - a3, - split("next", marker), - a1, - split("start", "1"), - a2, - split("end", "1"), - b3, - split("end", marker), - ], - }); - } - { - const result = combineContextsFunction({ - contextA: [ - a1, - split("start", "1"), - a2, - split("start", "2"), - a3, - ] satisfies Context[], - contextB: [ - a1, - split("start", "1"), - a2, - split("start", "2"), - b3, - ] satisfies Context[], - }) as { context: Context[] }; - - deepStrictEqual(result, { - context: [ - a1, - split("start", "1"), - a2, - split("start", "2"), - a3, - split("next", "2"), - b3, - split("end", "2"), - ], - }); - } - }); - - test("handles `single` scenario", () => { - const a1 = text("a1"); - const a2 = text("a2"); - const b1 = text("b1"); - const c1 = text("c1"); - const start = split("start", "1"); - const result = combineContextsFunction({ - contextA: [a1, a2, start], - contextB: [b1], - contextC: [c1], - } satisfies Record) as { context: Context[] }; - deepStrictEqual(result, { - context: [a1, a2, start, b1, split("next", "1"), c1, split("end", "1")], - }); - }); - - test("merges contexts when asked", () => { - const a1 = { text: "Before" }; - const a2 = { text: "Hello" }; - const b1 = { text: "In a" }; - const b2 = { text: "world" }; - const result = combineContextsFunction({ - contextA: [{ parts: [a1] }, { parts: [a2] }] satisfies LlmContent[], - contextB: [{ parts: [b1] }, { parts: [b2] }] satisfies LlmContent[], - merge: true, - }); - - deepStrictEqual(result, { - context: [{ parts: [a2, b2], role: "user" }], - }); - }); - - test("merges context with metadata", () => { - const a1 = { text: "a1" }; - const a2 = { text: "a2" }; - const b1 = { text: "b1" }; - const b2 = { text: "b2" }; - const result = combineContextsFunction({ - contextA: [ - { parts: [a1] }, - { parts: [a2] }, - split("end", "1"), - ] satisfies Context[], - contextB: [{ parts: [b1] }, { parts: [b2] }] satisfies LlmContent[], - merge: true, - }); - - deepStrictEqual(result, { - context: [{ parts: [a2, b2], role: "user" }], - }); - }); -}); diff --git a/packages/agent-kit/tests/function-calling.ts b/packages/agent-kit/tests/function-calling.ts deleted file mode 100644 index 913ad56a931..00000000000 --- a/packages/agent-kit/tests/function-calling.ts +++ /dev/null @@ -1,610 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { - FunctionCallFlags, - ToolResponse, - URLMap, - boardInvocationAssemblerFunction, - functionOrTextRouterFunction, - functionSignatureFromBoardFunction, - responseCollatorFunction, - resultFormatterFunction, -} from "../src/function-calling.js"; -import { deepStrictEqual, ok, throws } from "node:assert"; -import { - FunctionCall, - FunctionCallPart, - LlmContent, - splitStartAdderFunction, -} from "../src/context.js"; -import { GraphDescriptor } from "@google-labs/breadboard"; -import { readFile } from "node:fs/promises"; -import { resolve } from "path"; - -describe("function-calling/functionOrTextRouterFunction", () => { - test("throws when no context is supplied", () => { - throws(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - functionOrTextRouterFunction({} as any); - }); - }); - - test("throws when no text or function call is found", () => { - throws(() => { - functionOrTextRouterFunction({ - context: { - parts: [], - }, - }); - }); - }); - - test("handles text", () => { - const context = { - parts: [{ text: "Hello" }], - }; - const result = functionOrTextRouterFunction({ - context, - }); - deepStrictEqual(result, { context, text: "Hello" }); - }); - - test("handles function call", () => { - const context = { - parts: [ - { - functionCall: { - name: "Get_Web_Page_Content", - args: { - url: "https://example.com/", - }, - }, - }, - ], - }; - const result = functionOrTextRouterFunction({ - context, - }); - deepStrictEqual(result, { - context, - functionCalls: [ - { - name: "Get_Web_Page_Content", - args: { - url: "https://example.com/", - }, - }, - ], - }); - }); - - test("handles multiple parts", () => { - { - const context = { - parts: [{ text: "Hello" }, { text: "World" }], - }; - const result = functionOrTextRouterFunction({ - context, - }); - deepStrictEqual(result, { context, text: "Hello" }); - } - { - const context = { - parts: [ - { text: "Hello" }, - { - functionCall: { - name: "Get_Web_Page_Content", - args: { - url: "https://example.com/", - }, - }, - }, - ], - }; - const result = functionOrTextRouterFunction({ - context, - }); - deepStrictEqual(result, { - context, - functionCalls: [ - { - name: "Get_Web_Page_Content", - args: { - url: "https://example.com/", - }, - }, - ], - }); - } - { - const context = { - parts: [ - { - functionCall: { - name: "Get_Web_Page_Content", - args: { - url: "https://example.com/", - }, - }, - }, - { text: "Hello" }, - ], - }; - const result = functionOrTextRouterFunction({ - context, - }); - deepStrictEqual(result, { - context, - functionCalls: [ - { - name: "Get_Web_Page_Content", - args: { - url: "https://example.com/", - }, - }, - ], - }); - } - }); - - test("handles multiple function calls", () => { - const functionCall1 = { - name: "Get_Web_Page_Content", - args: { - url: "https://example.com/", - }, - }; - const functionCall2 = { - name: "Get_Next_Holiday", - args: { - country: "LT", - }, - }; - const context = { - parts: [{ functionCall: functionCall1 }, { functionCall: functionCall2 }], - }; - const result = functionOrTextRouterFunction({ context }); - deepStrictEqual(result, { - context, - functionCalls: [functionCall1, functionCall2], - }); - }); -}); - -describe("function-calling/boardInvocationAssembler", () => { - test("throws when the args are missing", () => { - throws(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - boardInvocationAssemblerFunction({} as any); - }, 'Must have "functionCalls".'); - throws(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - boardInvocationAssemblerFunction({ functionCalls: [] } as any); - }, 'Must have "urlMap"'); - throws(() => { - boardInvocationAssemblerFunction({ functionCalls: [], urlMap: {} }); - }, "Function call array must not be empty"); - }); - - test("correctly packs the invocation args", () => { - const functionCalls: FunctionCall[] = [ - { - name: "Get_Web_Page_Content", - args: { url: "https://example.com/" }, - }, - { - name: "Get_Next_Holiday", - args: { - country: "LT", - }, - }, - ] satisfies FunctionCallPart["functionCall"][]; - const urlMap = { - Get_Web_Page_Content: { url: "get/web/page", flags: {} }, - Get_Next_Holiday: { url: "get/next/holiday", flags: {} }, - } satisfies URLMap; - const result = boardInvocationAssemblerFunction({ functionCalls, urlMap }); - deepStrictEqual(result, { - list: [ - { $board: "get/web/page", url: "https://example.com/", $flags: {} }, - { $board: "get/next/holiday", country: "LT", $flags: {} }, - ], - routes: [], - }); - }); - - test("correctly packs the invocation args with flags", () => { - const functionCalls: FunctionCall[] = [ - { - name: "Get_Web_Page_Content", - args: { url: "https://example.com/" }, - }, - { - name: "Get_Next_Holiday", - args: { - country: "LT", - }, - }, - ] satisfies FunctionCallPart["functionCall"][]; - const urlMap = { - Get_Web_Page_Content: { - url: "get/web/page", - flags: { inputLLMContent: "url" }, - }, - Get_Next_Holiday: { - url: "get/next/holiday", - flags: { outputLLMContent: "holidays" }, - }, - } satisfies URLMap; - const result = boardInvocationAssemblerFunction({ functionCalls, urlMap }); - deepStrictEqual(result, { - list: [ - { - $board: "get/web/page", - url: { parts: [{ text: "https://example.com/" }], role: "user" }, - $flags: { inputLLMContent: "url" }, - }, - { - $board: "get/next/holiday", - country: "LT", - $flags: { outputLLMContent: "holidays" }, - }, - ], - routes: [], - }); - }); - - test("correctly packs the invocation args with array input flag", () => { - const functionCalls: FunctionCall[] = [ - { - name: "Get_Web_Page_Content", - args: { url: "https://example.com/" }, - }, - { - name: "Get_Next_Holiday", - args: { - country: "LT", - }, - }, - ]; - const urlMap = { - Get_Web_Page_Content: { - url: "get/web/page", - flags: { inputLLMContentArray: "url" }, - }, - Get_Next_Holiday: { - url: "get/next/holiday", - flags: { outputLLMContent: "holidays" }, - }, - } satisfies URLMap; - const result = boardInvocationAssemblerFunction({ functionCalls, urlMap }); - deepStrictEqual(result, { - list: [ - { - $board: "get/web/page", - url: [{ parts: [{ text: "https://example.com/" }], role: "user" }], - $flags: { inputLLMContentArray: "url" }, - }, - { - $board: "get/next/holiday", - country: "LT", - $flags: { outputLLMContent: "holidays" }, - }, - ], - routes: [], - }); - }); -}); - -describe("function-calling/resultFormatterFunction", () => { - test("correctly outputs LLMContent for simple outputs", () => { - { - const result = { data: "foo" }; - const output = resultFormatterFunction({ result, flags: {} }); - deepStrictEqual(output, { - item: [{ parts: [{ text: JSON.stringify(result) }], role: "tool" }], - }); - } - { - const result = { data: null }; - const output = resultFormatterFunction({ result, flags: {} }); - deepStrictEqual(output, { - item: [{ parts: [{ text: JSON.stringify(result) }], role: "tool" }], - }); - } - }); - test("correctly detect LLMContent inside (old way)", () => { - { - const result = { out: { content: "foo" } }; - const output = resultFormatterFunction({ result }); - deepStrictEqual(output, { - item: [{ parts: [{ text: JSON.stringify(result) }], role: "tool" }], - }); - } - { - const result = { - out: { - content: { parts: [{ text: "hello" }], role: "something" }, - }, - }; - const output = resultFormatterFunction({ result }); - deepStrictEqual(output, { - item: [{ parts: result.out.content.parts, role: "tool" }], - }); - } - }); - test("correctly detect LLMContent inside using flags", () => { - { - const llmContent: LlmContent = { parts: [{ text: "hello" }] }; - const result = { out: llmContent }; - const output = resultFormatterFunction({ - result, - flags: { outputLLMContent: "out" }, - }); - deepStrictEqual(output, { - item: [{ parts: [{ text: "hello" }], role: "tool" }], - }); - } - { - const llmContentArray: LlmContent[] = [ - { parts: [{ text: "hello" }] }, - { parts: [{ text: "world" }] }, - ]; - const result = { out: llmContentArray }; - const output = resultFormatterFunction({ - result, - flags: { outputLLMContentArray: "out" }, - }); - deepStrictEqual(output, { - item: [ - { parts: [{ text: "hello" }], role: "tool" }, - { parts: [{ text: "world" }], role: "tool" }, - ], - }); - } - }); -}); - -const loadBoard = async (name: string) => { - const board = await readFile( - resolve( - new URL(import.meta.url).pathname, - `../../../tests/boards/${name}.json` - ), - "utf8" - ); - return JSON.parse(board); -}; - -describe("function-calling/functionSignatureFromBoardFunction", () => { - test("throws when no board is supplied", () => { - throws(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - functionSignatureFromBoardFunction({} as any); - }); - }); - - test("handles boards with no inputs", async () => { - const board = await loadBoard("today"); - const result = functionSignatureFromBoardFunction({ - board, - }); - deepStrictEqual(result.board, board); - delete (result as Partial).board; - deepStrictEqual(result, { - function: { - name: "Get_Today", - description: "Return today's date", - }, - returns: { - type: "object", - properties: { - today: { - title: "Today", - type: "string", - examples: [], - }, - }, - required: [], - }, - flags: {}, - }); - }); - - test("throws when no outputs are found", () => { - const board = { - nodes: [ - { - id: "node-1", - type: "input", - }, - ], - edges: [], - } satisfies GraphDescriptor; - throws(() => { - functionSignatureFromBoardFunction({ - board, - }); - }); - }); - test("throws when no input schema is found", () => { - const board = { - nodes: [ - { - id: "node-1", - type: "input", - configuration: {}, - }, - { - id: "node-1", - type: "output", - configuration: {}, - }, - ], - edges: [], - } satisfies GraphDescriptor; - throws(() => { - functionSignatureFromBoardFunction({ - board, - }); - }); - }); - - test("returns function signature and return values", async () => { - const board = await loadBoard("next-public-holiday"); - const result = functionSignatureFromBoardFunction({ - board, - }); - deepStrictEqual(result.board, board); - delete (result as Partial).board; - deepStrictEqual(result, { - function: { - name: "Nager_Date_Next_Public_Holiday", - description: "Get the next public holiday for a given country", - parameters: { - type: "object", - properties: { - countryCode: { - type: "string", - description: "Two-letter country code", - }, - }, - }, - }, - returns: { - type: "object", - properties: { - holidays: { - description: "A list of public holidays for the given country", - title: "Holidays", - type: ["array", "boolean", "null", "number", "object", "string"], - }, - }, - required: ["holidays"], - }, - flags: {}, - }); - }); - - test("recognizes and flags LLM content", async () => { - const board = await loadBoard("holiday-researcher"); - const result = functionSignatureFromBoardFunction({ - board, - }) as { flags: FunctionCallFlags }; - deepStrictEqual(result.flags, { - inputLLMContent: "text", - outputLLMContent: "text", - }); - }); - - test("recognizes and flags LLM content arrays", async () => { - const board = await loadBoard("llm-content-array"); - const result = functionSignatureFromBoardFunction({ - board, - }) as { flags: FunctionCallFlags }; - deepStrictEqual(result.flags, { - inputLLMContentArray: "text", - outputLLMContentArray: "text", - }); - }); - - // test("substitutes property title for description when description is missing", async () => { - // const board = await loadBoard("no-descriptions"); - // const result = functionSignatureFromBoardFunction({ - // board, - // }) as { function: Record }; - // deepStrictEqual(result.function.parameters, { - // type: "object", - // properties: { - // text: { - // type: "string", - // description: "text", - // }, - // }, - // }); - // }); - - test("elides property named `context` from args", async () => { - const board = await loadBoard("context-arg"); - const result = functionSignatureFromBoardFunction({ - board, - }) as { function: Record }; - ok(!result.function.parameters); - }); - - test("renames the arg named `context` to match property name", async () => { - const board = await loadBoard("context-arg"); - const result = functionSignatureFromBoardFunction({ - board, - // eslint-disable-next-line @typescript-eslint/ban-types - }) as {} as { board: GraphDescriptor }; - ok(result.board.args?.["property-1"]); - }); -}); - -describe("function-calling/responseCollator", () => { - const generated: LlmContent = { - parts: [ - { - functionCall: { - name: "Get_Web_Page_Content", - args: { url: "https://example.com/" }, - }, - }, - ], - }; - const hello: LlmContent = { parts: [{ text: "Hello" }], role: "tool" }; - const world: LlmContent = { parts: [{ text: "World" }], role: "tool" }; - const howdy: LlmContent = { parts: [{ text: "Howdy" }], role: "tool" }; - const realm: LlmContent = { parts: [{ text: "Realm" }], role: "tool" }; - test("correctly collates responses", () => { - const response: ToolResponse[] = [ - { item: [hello, world] }, - { item: [howdy, realm] }, - ]; - const result = responseCollatorFunction({ response, generated }); - deepStrictEqual(result, { - "context-1": [generated], - "context-2": [hello, world], - "context-3": [howdy, realm], - }); - }); - test("correctly adds context", () => { - const context: LlmContent[] = [hello, world]; - const response = [{ item: [howdy, realm] }] satisfies ToolResponse[]; - const result = responseCollatorFunction({ response, context, generated }); - deepStrictEqual(result, { - "context-0": [hello, world], - "context-1": [generated], - "context-2": [howdy, realm], - }); - }); -}); - -describe("function-calling/addSplitStart", () => { - test("correctly adds split start", () => { - const hello: LlmContent = { parts: [{ text: "Hello" }], role: "tool" }; - const context: LlmContent[] = [hello]; - const result = splitStartAdderFunction({ - context, - }); - const c = result.context as LlmContent[]; - ok(c.length === 2); - ok(result.id !== null); - const id = result.id; - deepStrictEqual(c[1], { - role: "$metadata", - type: "split", - data: { - id, - type: "start", - }, - }); - }); -}); diff --git a/packages/agent-kit/tests/human.ts b/packages/agent-kit/tests/human.ts deleted file mode 100644 index 2f5fa164229..00000000000 --- a/packages/agent-kit/tests/human.ts +++ /dev/null @@ -1,135 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { - pickChoice, - buildChooseSchema, - routeByMode, -} from "../src/boards/human.js"; -import { Context, LlmContentRole, SplitMarkerData } from "../src/context.js"; -import { deepStrictEqual } from "node:assert"; - -const text = (text: string, role: LlmContentRole): Context => { - return { parts: [{ text }], role }; -}; - -const split = (type: SplitMarkerData["type"], id: string): Context => { - return { role: "$metadata", type: "split", data: { id, type } }; -}; - -const looper = (): Context => { - return { role: "$metadata", type: "looper", data: {} }; -}; - -describe("human/modeRouterFunction", () => { - test("correctly recognizes the `input` mode when context is empty", () => { - const context: Context[] = []; - const result = routeByMode.test({ context }); - deepStrictEqual(result, { input: context }); - }); - test("correctly recognizes the `input` mode", () => { - const context: Context[] = [text("Hello", "user")]; - const result = routeByMode.test({ context }); - deepStrictEqual(result, { input: context }); - }); - test("correctly recognizes the `input-output` mode", () => { - const context: Context[] = [text("Hello", "model")]; - const result = routeByMode.test({ context }); - deepStrictEqual(result, { input: context, output: context }); - }); - test("correctly recognizes the `choose` mode", () => { - { - const context: Context[] = [looper()]; - const result = routeByMode.test({ context }); - deepStrictEqual(result, { input: context, output: context }); - } - { - const context: Context[] = [split("end", "1")]; - const result = routeByMode.test({ context }); - deepStrictEqual(result, { output: context, input: context }); - } - { - const context: Context[] = [ - split("start", "1"), - split("next", "1"), - split("end", "1"), - ]; - const result = routeByMode.test({ context }); - deepStrictEqual(result, { output: context, choose: context }); - } - { - const context: Context[] = [split("start", "1"), split("end", "1")]; - const result = routeByMode.test({ context }); - deepStrictEqual(result, { output: context, input: context }); - } - { - const context: Context[] = [ - split("start", "2"), - split("next", "1"), - split("end", "1"), - ]; - const result = routeByMode.test({ context }); - deepStrictEqual(result, { output: context, input: context }); - } - }); -}); - -describe("human/buildChooseSchema", () => { - test("correctly builds the schema for the `choose` mode", () => { - const context: Context[] = [ - split("start", "2"), - text("1", "tool"), - split("next", "2"), - text("2", "tool"), - split("end", "1"), - ]; - const title = "Choose"; - const description = "Choose some options"; - const result = buildChooseSchema.test({ - context, - title, - description, - }); - deepStrictEqual(result, { - schema: { - type: "object", - properties: { - choice: { - title, - description, - type: "string", - enum: ["Choice 1", "Choice 2"], - }, - }, - }, - total: 2, - }); - }); -}); - -describe("human/pickChoice", () => { - test("correctly picks the choice", () => { - const context: Context[] = [ - text("0", "model"), - split("start", "2"), - text("1", "tool"), - split("next", "2"), - text("2", "tool"), - text("2.5", "tool"), - split("next", "2"), - text("3", "tool"), - split("end", "2"), - ]; - const choice = "Choice 2"; - const total = 3; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const result = pickChoice.test({ context, choice, total }); - deepStrictEqual(result, { - context: [text("0", "model"), text("2", "tool"), text("2.5", "tool")], - }); - }); -}); diff --git a/packages/agent-kit/tests/looper.ts b/packages/agent-kit/tests/looper.ts deleted file mode 100644 index d2642dba6e0..00000000000 --- a/packages/agent-kit/tests/looper.ts +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { planReaderFunction } from "../src/boards/looper.js"; -import { throws, deepStrictEqual } from "node:assert"; -import { Context, LooperPlan } from "../src/context.js"; - -const tasks = (...tasks: string[]): LooperPlan => { - return { - todo: tasks.map((task) => ({ task })), - }; -}; - -describe("planReader", () => { - test("throws when no plan is supplied", () => { - throws(() => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - planReaderFunction({} as any); - }); - }); - - test("correctly shifts tasks", () => { - const context: Context[] = []; - const progress = tasks("Task 1", "Task 2"); - const result = planReaderFunction({ - context, - progress, - }); - deepStrictEqual(result, { - context: [ - { - role: "$metadata", - type: "looper", - data: { - todo: [{ task: "Task 2" }], - next: "Task 1", - } satisfies LooperPlan, - }, - ] satisfies Context[], - }); - }); - - test("favors todo over doneMarker when both are present", () => { - const context: Context[] = []; - const progress = tasks("Task 1", "Task 2"); - progress.doneMarker = "marker"; - const result = planReaderFunction({ - context, - progress, - }); - deepStrictEqual(result, { - context: [ - { - role: "$metadata", - type: "looper", - data: { - todo: [{ task: "Task 2" }], - next: "Task 1", - } satisfies LooperPlan, - }, - ] satisfies Context[], - }); - }); -}); diff --git a/packages/agent-kit/tests/templating.ts b/packages/agent-kit/tests/templating.ts deleted file mode 100644 index f22ed26e05a..00000000000 --- a/packages/agent-kit/tests/templating.ts +++ /dev/null @@ -1,494 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { describe, it } from "node:test"; -import { InlineDataCapabilityPart } from "@google-labs/breadboard"; -import { deepStrictEqual, ok } from "node:assert"; -import { - describeSpecialist, - content, - describeContent, -} from "../src/templating.js"; -import { LlmContent } from "../src/context.js"; -import { run as substitute } from "../src/js-components/substitute.js"; - -describe("Templating", () => { - it("does simple substitution", async () => { - const context: LlmContent[] = []; - const persona = llmContent("user", "You're a {{character}}, {{name}}."); - const task = llmContent("user", "Act like a {{character}}."); - const character = "wizard"; - const result = substitute({ - in: context, - persona, - task, - ["p-character" as never]: character, - ["p-name" as never]: "Harry", - }); - deepStrictEqual(result, { - in: [], - persona: llmContent("user", "You're a wizard, Harry."), - task: llmContent("user", "Act like a wizard."), - outs: [], - }); - }); - - it("does simple substitution with whitespaces in params", async () => { - const context: LlmContent[] = []; - const persona = llmContent("user", "You're a {{ character}}, {{ name }}."); - const task = llmContent("user", "Act like a {{character }}."); - const character = "wizard"; - const result = substitute({ - in: context, - persona, - task, - ["p-character" as never]: character, - ["p-name" as never]: "Harry", - }); - deepStrictEqual(result, { - in: [], - persona: llmContent("user", "You're a wizard, Harry."), - task: llmContent("user", "Act like a wizard."), - outs: [], - }); - }); - - it("does simple substitution with op and arg", async () => { - const context: LlmContent[] = []; - const persona = llmContent( - "user", - "You're a {{ character | out }}, {{ name | in }}." - ); - const task = llmContent("user", 'Act like a {{character | out: "test" }}.'); - const character = "wizard"; - const result = substitute({ - in: context, - persona, - task, - ["p-character" as never]: character, - ["p-name" as never]: "Harry", - }); - deepStrictEqual(result, { - in: [], - persona: llmContent("user", 'You\'re a "TOOL_CHARACTER", Harry.'), - task: llmContent("user", 'Act like a "TOOL_CHARACTER".'), - outs: [ - { - name: "TOOL_CHARACTER", - description: - 'Call this function when asked to invoke the "TOOL_CHARACTER" tool.', - }, - ], - }); - }); - - it("does simple LLM Content object substitution", async () => { - const context: LlmContent[] = []; - const persona = llmContent("user", "You're a {{character}}, {{name}}."); - const task = llmContent("user", "Act like a {{character}}."); - const character = llmContent("user", "wizard"); - const name = llmContent("user", "Harry"); - const result = substitute({ - in: context, - persona, - task, - ["p-character" as never]: character, - ["p-name" as never]: name, - }); - deepStrictEqual(result, { - in: [], - persona: llmContent("user", "You're a wizard, Harry."), - task: llmContent("user", "Act like a wizard."), - outs: [], - }); - }); - - it("does part-splicing LLM Content object substitution", async () => { - const context: LlmContent[] = []; - const persona = llmContent("user", "You're a {{character}}, {{name}}."); - const task = llmContent("user", "Act like a {{character}}."); - const character = llmContent("user", "wizard"); - const name = llmContent("user", "Harry", " ", "Potter"); - const result = substitute({ - in: context, - persona, - task, - ["p-character" as never]: character, - ["p-name" as never]: name, - }); - deepStrictEqual(result, { - in: [], - persona: llmContent("user", "You're a wizard, Harry Potter."), - task: llmContent("user", "Act like a wizard."), - outs: [], - }); - }); - - it("works with LLM Content Array arguments", async () => { - const context: LlmContent[] = []; - const persona = llmContent("user", "You're a {{character}}, {{name}}."); - const task = llmContent("user", "Act like a {{character}}."); - const character = [llmContent("user", "wizard")]; - const name = [llmContent("user", "Harry", " ", "Potter")]; - const result = substitute({ - in: context, - persona, - task, - ["p-character" as never]: character, - ["p-name" as never]: name, - }); - deepStrictEqual(result, { - in: [], - persona: llmContent("user", "You're a wizard, Harry Potter."), - task: llmContent("user", "Act like a wizard."), - outs: [], - }); - }); - - it("works with other primitive types", async () => { - const context: LlmContent[] = []; - const persona = llmContent("user", "You're a {{character}}, {{name}}."); - const task = llmContent("user", "Act like a {{character}}."); - const character = true; - const name = 42; - const result = substitute({ - in: context, - persona, - task, - ["p-character" as never]: character, - ["p-name" as never]: name, - }); - deepStrictEqual(result, { - in: [], - persona: llmContent("user", "You're a true, 42."), - task: llmContent("user", "Act like a true."), - outs: [], - }); - }); - - it("works with arbitrary objects", async () => { - const context: LlmContent[] = []; - const persona = llmContent("user", "You're a {{character}}, {{name}}."); - const task = llmContent("user", "Act like a {{character}}."); - const character = { wizard: true }; - const name = "Harry"; - const result = substitute({ - in: context, - persona, - task, - ["p-character" as never]: character, - ["p-name" as never]: name, - }); - deepStrictEqual(result, { - in: [], - persona: llmContent("user", 'You\'re a {"wizard":true}, Harry.'), - task: llmContent("user", 'Act like a {"wizard":true}.'), - outs: [], - }); - }); - - it("works with other part types", async () => { - const context: LlmContent[] = []; - const persona = llmContent("user", "You're a {{character}}, {{name}}."); - const task = llmContent("user", "Act like a {{character}}."); - const character = llmContent("user", "wizard"); - const name = llmContent( - "user", - "Harry", - inlineData("potter", "text/plain") - ); - const result = substitute({ - in: context, - persona, - task, - ["p-character" as never]: character, - ["p-name" as never]: name, - }); - deepStrictEqual(result, { - in: [], - persona: llmContent( - "user", - "You're a wizard, Harry", - inlineData("potter", "text/plain"), - "." - ), - task: llmContent("user", "Act like a wizard."), - outs: [], - }); - }); -}); - -describe("Content component", () => { - it("does simple forwarding of content", () => { - const context = [llmContent("user", "You're a wizard, Harry.")]; - const template = llmContent("user"); - const result = content({ context, template }); - deepStrictEqual(result, { - context: [llmContent("user", "You're a wizard, Harry.")], - }); - }); - - it("correcly elides empty context", () => { - const context: LlmContent[] = []; - const template = llmContent("user", "You're a wizard, Harry."); - const result = content({ context, template }); - deepStrictEqual(result, { - context: [llmContent("user", "You're a wizard, Harry.")], - }); - }); - - it("handles empty template", () => { - const context = [llmContent("user", "You're a wizard, Harry.")]; - const template = undefined; - const result = content({ context, template }); - deepStrictEqual(result, { - context: [llmContent("user", "You're a wizard, Harry.")], - }); - }); - - it("does simple substitution", () => { - const context: LlmContent[] = []; - const template = llmContent("user", "Act like a {{role}}."); - const role = "wizard"; - const result = content({ context, template, "p-role": role }); - deepStrictEqual(result, { - context: [llmContent("user", "Act like a wizard.")], - }); - }); - - it("does simple LLM Content object substitution", () => { - const context: LlmContent[] = []; - const template = llmContent("user", "Act like a {{role}}."); - const role = llmContent("user", "wizard"); - const result = content({ context, template, "p-role": role }); - deepStrictEqual(result, { - context: [llmContent("user", "Act like a wizard.")], - }); - }); - - it("correctly prepends context", () => { - const context = [llmContent("model", "You're a wizard, Harry.")]; - const template = llmContent("user", "Act like a {{role}}."); - const role = llmContent("user", "wizard"); - const result = content({ context, template, "p-role": role }); - deepStrictEqual(result, { - context: [ - llmContent("model", "You're a wizard, Harry."), - llmContent("user", "Act like a wizard."), - ], - }); - }); - - it("correctly merges with context in user role", () => { - const context = [llmContent("user", "You're a wizard, Harry.")]; - const template = llmContent("user", "Act like a {{role}}."); - const role = llmContent("user", "wizard"); - const result = content({ context, template, "p-role": role }); - deepStrictEqual(result, { - context: [ - llmContent("user", "You're a wizard, Harry.", "Act like a wizard."), - ], - }); - }); -}); - -describe("Specialist v2 describer", () => { - it("correctly collects parameters", () => { - const $inputSchema = {}; - const $outputSchema = {}; - const persona = llmContent("user", "You're a {{character}}, {{name}}."); - const task = llmContent("user", "Act like a {{character}}."); - - const result = describeSpecialist({ - $inputSchema, - $outputSchema, - persona, - task, - }); - - const paramProps = result.inputSchema.properties; - delete paramProps.in; - delete paramProps.persona; - delete paramProps.task; - deepStrictEqual(paramProps, { - "p-character": { - description: 'The value to substitute for the parameter "character"', - title: "Character", - type: "string", - }, - "p-name": { - description: 'The value to substitute for the parameter "name"', - title: "Name", - type: "string", - }, - }); - }); - - it("handles whitespace in parameter names", () => { - const $inputSchema = {}; - const $outputSchema = {}; - const persona = llmContent("user", "You're a {{ character}}, {{ name }}."); - const task = llmContent("user", "Act like a {{character }}."); - - const result = describeSpecialist({ - $inputSchema, - $outputSchema, - persona, - task, - }); - - const paramProps = result.inputSchema.properties; - delete paramProps.in; - delete paramProps.persona; - delete paramProps.task; - deepStrictEqual(paramProps, { - "p-character": { - description: 'The value to substitute for the parameter "character"', - title: "Character", - type: "string", - }, - "p-name": { - description: 'The value to substitute for the parameter "name"', - title: "Name", - type: "string", - }, - }); - }); - - it("recognizes outputs", () => { - const $inputSchema = {}; - const $outputSchema = {}; - const persona = llmContent("user", "You're a {{character}}, {{name}}."); - const task = llmContent("user", "Act like a {{character | out}}."); - - const result = describeSpecialist({ - $inputSchema, - $outputSchema, - persona, - task, - }); - - const paramProps = result.inputSchema.properties; - delete paramProps.in; - delete paramProps.persona; - delete paramProps.task; - deepStrictEqual(paramProps, { - "p-character": { - description: 'The value to substitute for the parameter "character"', - title: "Character", - type: "string", - }, - "p-name": { - description: 'The value to substitute for the parameter "name"', - title: "Name", - type: "string", - }, - }); - const outputProps = result.outputSchema.properties; - ok(outputProps); - delete outputProps.out; - deepStrictEqual(outputProps, { - "p-TOOL_CHARACTER": { - description: 'The output chosen when the "character" tool is invoked', - title: "Character", - type: "string", - }, - }); - }); -}); - -describe("Content describer", () => { - it("works without params", () => { - const $inputSchema = {}; - const $outputSchema = {}; - const template = llmContent("user", "Act like a wizard."); - - const result = describeContent({ - $inputSchema, - $outputSchema, - template, - }); - - const paramProps = result.inputSchema.properties; - delete paramProps.context; - delete paramProps.template; - - deepStrictEqual(paramProps, {}); - }); - - it("correctly collects parameters", () => { - const $inputSchema = {}; - const $outputSchema = {}; - const template = llmContent("user", "Act like a {{role}}."); - - const result = describeContent({ - $inputSchema, - $outputSchema, - template, - }); - - const paramProps = result.inputSchema.properties; - delete paramProps.context; - delete paramProps.template; - deepStrictEqual(paramProps, { - "p-role": { - description: 'The value to substitute for the parameter "role"', - title: "Role", - type: "string", - }, - }); - }); - - it("handles whitespace in parameter names", () => { - const $inputSchema = {}; - const $outputSchema = {}; - const template = llmContent("user", "Act like a {{ role }}."); - - const result = describeContent({ - $inputSchema, - $outputSchema, - template, - }); - - const paramProps = result.inputSchema.properties; - delete paramProps.context; - delete paramProps.template; - deepStrictEqual(paramProps, { - "p-role": { - description: 'The value to substitute for the parameter "role"', - title: "Role", - type: "string", - }, - }); - }); -}); - -function inlineData(data: string, mimeType: string): InlineDataCapabilityPart { - return { - inlineData: { - data, - mimeType, - }, - }; -} - -function llmContent( - role: "user" | "model", - ...text: (string | InlineDataCapabilityPart)[] -): LlmContent { - if (text.length === 0) { - return { parts: [{ text: "" }], role }; - } - return { - role, - parts: text.map((t) => { - if (typeof t === "string") { - return { text: t }; - } - return t; - }), - } as LlmContent; -} diff --git a/packages/agent-kit/tsconfig.json b/packages/agent-kit/tsconfig.json deleted file mode 100644 index cb53396a8bf..00000000000 --- a/packages/agent-kit/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "rootDir": ".", - "outDir": "./dist", - "resolveJsonModule": true - }, - "include": ["src/**/*", "tests/**/*"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/board-server-management/.eslintrc b/packages/board-server-management/.eslintrc deleted file mode 100644 index f72cccfe73a..00000000000 --- a/packages/board-server-management/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"] - } -} diff --git a/packages/board-server-management/.gitignore b/packages/board-server-management/.gitignore deleted file mode 100644 index c819d9232a7..00000000000 --- a/packages/board-server-management/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# pyodide assets that we copy into public/. We don't want to check these in -# because they come from NPM. -public/pyodide* -public/python* \ No newline at end of file diff --git a/packages/board-server-management/CHANGELOG.md b/packages/board-server-management/CHANGELOG.md deleted file mode 100644 index e478c12c7a3..00000000000 --- a/packages/board-server-management/CHANGELOG.md +++ /dev/null @@ -1,58 +0,0 @@ -# @breadboard-ai/board-server-management - -## 1.17.0 - -### Minor Changes - -- 157c31e: Implement remote board server -- 60349b8: Add board server management and remote board server packages - -### Patch Changes - -- Updated dependencies [49e2740] -- Updated dependencies [54c8197] -- Updated dependencies [703f17d] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [8f9fddf] -- Updated dependencies [2fa05f0] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [f71bcfb] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [3188607] -- Updated dependencies [9797718] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [8330f0c] -- Updated dependencies [a039d2e] -- Updated dependencies [1423647] -- Updated dependencies [9783ba8] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [91fe8bb] -- Updated dependencies [100fc95] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [5834c81] -- Updated dependencies [d7606d3] -- Updated dependencies [0ef793f] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] -- Updated dependencies [60349b8] - - @breadboard-ai/build@0.10.0 - - @google-labs/breadboard@0.27.0 - - @breadboard-ai/idb-board-server@1.17.0 - - @breadboard-ai/remote-board-server@1.17.0 diff --git a/packages/board-server-management/README.md b/packages/board-server-management/README.md deleted file mode 100644 index 8a1a3f77962..00000000000 --- a/packages/board-server-management/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Board Server Management - -Handles the setup of board servers for the Visual Editor diff --git a/packages/board-server-management/package.json b/packages/board-server-management/package.json deleted file mode 100644 index 931e6b5ff30..00000000000 --- a/packages/board-server-management/package.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "name": "@breadboard-ai/board-server-management", - "version": "1.17.0", - "description": "Board Server management for Breadboard's Visual Editor", - "main": "./dist/index.js", - "exports": { - ".": { - "default": "./dist/index.js", - "types": "./dist/index.d.ts" - } - }, - "types": "dist/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "build:tsc": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "../breadboard:build", - "../idb-board-server:build", - "../remote-board-server:build", - "build:tsc" - ] - }, - "typescript-files-and-deps": { - "dependencies": [ - "../breadboard:build:tsc", - "../idb-board-server:build:tsc", - "../remote-board-server:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "typescript-files-and-deps" - ], - "files": [], - "output": [ - "dist/", - "!dist/**/*.min.js{,.map}" - ], - "clean": "if-file-deleted" - } - }, - "repository": { - "directory": "packages/board-server-management", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/" - ], - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/board-server-management#readme", - "devDependencies": { - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "typescript": "^5.6.2" - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/idb-board-server": "^1.17.0", - "@breadboard-ai/remote-board-server": "^1.17.0", - "@google-labs/breadboard": "^0.27.0", - "idb": "^8.0.0" - } -} diff --git a/packages/board-server-management/src/index.ts b/packages/board-server-management/src/index.ts deleted file mode 100644 index 32a56da2a85..00000000000 --- a/packages/board-server-management/src/index.ts +++ /dev/null @@ -1,154 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as idb from "idb"; -import { IDBBoardServer } from "@breadboard-ai/idb-board-server"; -import { BoardServer, GraphDescriptor, User } from "@google-labs/breadboard"; -import { RemoteBoardServer } from "@breadboard-ai/remote-board-server"; - -const BOARD_SERVER_LISTING_DB = "board-server"; -const BOARD_SERVER_LISTING_VERSION = 1; - -interface BoardServerListing extends idb.DBSchema { - servers: { - key: "url"; - value: { - url: string; - user: User; - }; - }; -} - -export async function getBoardServers(): Promise { - const db = await idb.openDB( - BOARD_SERVER_LISTING_DB, - BOARD_SERVER_LISTING_VERSION, - { - upgrade(db) { - db.createObjectStore("servers", { keyPath: "url" }); - }, - } - ); - - const storeUrls = await db.getAll("servers"); - db.close(); - - const stores = await Promise.all( - storeUrls.map(({ url, user }) => { - if (url.startsWith(IDBBoardServer.PROTOCOL)) { - return IDBBoardServer.from(url, user); - } - - if (url.startsWith(RemoteBoardServer.PROTOCOL)) { - return RemoteBoardServer.from(url, user); - } - - console.warn(`Unsupported store URL: ${url}`); - return null; - }) - ); - - return stores.filter((store) => store !== null); -} - -export async function createBoardServer(url: URL, user: User) { - const db = await idb.openDB( - BOARD_SERVER_LISTING_DB, - BOARD_SERVER_LISTING_VERSION, - { - upgrade(db) { - db.createObjectStore("servers", { keyPath: "url" }); - }, - } - ); - - await db.put("servers", { url: url.href, user }); - db.close(); -} - -export async function createDefaultLocalBoardServer() { - try { - const url = `${IDBBoardServer.PROTOCOL}board-server-local`; - const user = { - username: "board-builder", - apiKey: "breadboard", - secrets: new Map(), - }; - - await createBoardServer(new URL(url), user); - await IDBBoardServer.createDefault(new URL(url), user); - } catch (err) { - console.warn(err); - } -} - -export async function migrateIDBGraphProviders() { - const db = await idb.openDB("default"); - const graphs: GraphDescriptor[] = await db.getAll("graphs"); - db.close(); - - const boardServers = await getBoardServers(); - const idbBoardServer = boardServers.find( - (bbs) => bbs.name === "Browser Storage" - ); - - if (idbBoardServer) { - for (let i = 0; i < graphs.length; i++) { - const descriptor = graphs[i]; - const boardSlug = descriptor.url?.split("/").at(-1) ?? "board.bgl.json"; - const boardUrl = new URL( - `${idbBoardServer.url.href}/project-${i}/${boardSlug}` - ); - - await idbBoardServer.create(boardUrl, descriptor); - } - } else { - console.warn("Unable to find local Board Server"); - } -} - -interface RemoteGraphProviderStore { - url: string; - apiKey: string; -} - -interface RemoteGraphProviderStoreList extends idb.DBSchema { - stores: { - key: string; - value: RemoteGraphProviderStore; - }; -} - -const STORE_LIST = "remote-store-list"; -const STORE_LIST_VERSION = 1; - -export async function migrateRemoteGraphProviders() { - const db = await idb.openDB( - STORE_LIST, - STORE_LIST_VERSION, - { - upgrade(database) { - database.createObjectStore("stores", { - keyPath: "id", - autoIncrement: true, - }); - }, - } - ); - - const stores = await db.getAll("stores"); - for (const store of stores) { - const user = { - // TODO: Replace this with the actual username. - username: "board-builder", - apiKey: store.apiKey, - secrets: new Map(), - }; - - await createBoardServer(new URL(store.url), user); - } - db.close(); -} diff --git a/packages/board-server-management/tsconfig.json b/packages/board-server-management/tsconfig.json deleted file mode 100644 index 40a3e9972c4..00000000000 --- a/packages/board-server-management/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "ESNext", - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - "experimentalDecorators": true, - "useDefineForClassFields": false, - "outDir": "dist", - - /* Bundler mode */ - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": false, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "types": ["vite/client"] - }, - "include": ["src/**/*.ts", "tests/**/*.ts"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/board-server-utils/.eslintrc b/packages/board-server-utils/.eslintrc deleted file mode 100644 index f72cccfe73a..00000000000 --- a/packages/board-server-utils/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"] - } -} diff --git a/packages/board-server-utils/.gitignore b/packages/board-server-utils/.gitignore deleted file mode 100644 index c819d9232a7..00000000000 --- a/packages/board-server-utils/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# pyodide assets that we copy into public/. We don't want to check these in -# because they come from NPM. -public/pyodide* -public/python* \ No newline at end of file diff --git a/packages/board-server-utils/CHANGELOG.md b/packages/board-server-utils/CHANGELOG.md deleted file mode 100644 index 79990e9440f..00000000000 --- a/packages/board-server-utils/CHANGELOG.md +++ /dev/null @@ -1,69 +0,0 @@ -# @breadboard-ai/board-server-utils - -## 0.1.1 - -### Patch Changes - -- Updated dependencies [49e2740] -- Updated dependencies [54c8197] -- Updated dependencies [f94f498] -- Updated dependencies [703f17d] -- Updated dependencies [8d06f3c] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [8f9fddf] -- Updated dependencies [2fa05f0] -- Updated dependencies [4e0a4f6] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [f71bcfb] -- Updated dependencies [a104fa7] -- Updated dependencies [f0b5ccc] -- Updated dependencies [8a1b8c4] -- Updated dependencies [3188607] -- Updated dependencies [58d2e8c] -- Updated dependencies [9797718] -- Updated dependencies [679719b] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [8330f0c] -- Updated dependencies [9b62fc2] -- Updated dependencies [a039d2e] -- Updated dependencies [e63b5dd] -- Updated dependencies [1423647] -- Updated dependencies [74d50d4] -- Updated dependencies [9783ba8] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [9ce8ad3] -- Updated dependencies [7fdf9c2] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [91fe8bb] -- Updated dependencies [e38bf19] -- Updated dependencies [100fc95] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [5834c81] -- Updated dependencies [d7606d3] -- Updated dependencies [0ef793f] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] -- Updated dependencies [e026112] -- Updated dependencies [94759f7] -- Updated dependencies [281ab28] -- Updated dependencies [5fc6e8b] - - @breadboard-ai/build@0.10.0 - - @google-labs/agent-kit@0.12.0 - - @google-labs/breadboard@0.27.0 - - @google-labs/breadboard-schema@1.8.0 - - @breadboard-ai/data-store@0.2.3 diff --git a/packages/board-server-utils/README.md b/packages/board-server-utils/README.md deleted file mode 100644 index 52e7d0ed763..00000000000 --- a/packages/board-server-utils/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Breadboard Board Server Utils - -A collection of handy utils for dealing with Board Servers. diff --git a/packages/board-server-utils/package.json b/packages/board-server-utils/package.json deleted file mode 100644 index 163d025a20b..00000000000 --- a/packages/board-server-utils/package.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "name": "@breadboard-ai/board-server-utils", - "version": "0.1.1", - "description": "Board Server Utilities", - "main": "./dist/index.js", - "exports": { - ".": { - "default": "./dist/index.js", - "types": "./dist/index.d.ts" - } - }, - "types": "dist/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "build:tsc": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "../breadboard:build", - "../build:build", - "build:tsc" - ] - }, - "typescript-files-and-deps": { - "dependencies": [ - "../breadboard:build:tsc", - "../build:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "typescript-files-and-deps" - ], - "files": [], - "output": [ - "dist/", - "!dist/**/*.min.js{,.map}" - ], - "clean": "if-file-deleted" - } - }, - "repository": { - "directory": "packages/board-server-utils", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/" - ], - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/board-server-utils#readme", - "devDependencies": { - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "typescript": "^5.6.2" - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/data-store": "^0.2.3", - "@google-labs/agent-kit": "^0.12.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/breadboard-schema": "^1.8.0" - } -} diff --git a/packages/board-server-utils/src/index.ts b/packages/board-server-utils/src/index.ts deleted file mode 100644 index 0fec19a5032..00000000000 --- a/packages/board-server-utils/src/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { BoardServer, GraphProvider } from "@google-labs/breadboard"; - -export async function copy( - _server1: GraphProvider | BoardServer, - _server2: GraphProvider | BoardServer -): Promise { - throw new Error("Not implemented yet"); -} - -export async function move( - _server1: GraphProvider | BoardServer, - _server2: GraphProvider | BoardServer -): Promise { - throw new Error("Not implemented yet"); -} diff --git a/packages/board-server-utils/tsconfig.json b/packages/board-server-utils/tsconfig.json deleted file mode 100644 index 40a3e9972c4..00000000000 --- a/packages/board-server-utils/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "ESNext", - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - "experimentalDecorators": true, - "useDefineForClassFields": false, - "outDir": "dist", - - /* Bundler mode */ - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": false, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "types": ["vite/client"] - }, - "include": ["src/**/*.ts", "tests/**/*.ts"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/board-server/.env.development b/packages/board-server/.env.development deleted file mode 100644 index 49a403d64eb..00000000000 --- a/packages/board-server/.env.development +++ /dev/null @@ -1 +0,0 @@ -VITE_CONNECTION_SERVER_URL=http://localhost:5555 \ No newline at end of file diff --git a/packages/board-server/.env.production b/packages/board-server/.env.production deleted file mode 100644 index ddf5685f147..00000000000 --- a/packages/board-server/.env.production +++ /dev/null @@ -1,3 +0,0 @@ -# To connect the Board Server App to a Connection Server, provide the Connection -# Server URL here. -VITE_CONNECTION_SERVER_URL= diff --git a/packages/board-server/.gcloudignore b/packages/board-server/.gcloudignore deleted file mode 100644 index 029ff38a96a..00000000000 --- a/packages/board-server/.gcloudignore +++ /dev/null @@ -1,6 +0,0 @@ -.gcloudignore -.git -.gitignore -node_modules/ -.wireit/ -tests/ \ No newline at end of file diff --git a/packages/board-server/CHANGELOG.md b/packages/board-server/CHANGELOG.md deleted file mode 100644 index c6a7162e554..00000000000 --- a/packages/board-server/CHANGELOG.md +++ /dev/null @@ -1,306 +0,0 @@ -# @breadboard-ai/board-server - -## 0.7.0 - -### Minor Changes - -- 8f9fddf: Move LightObserver to shared-ui as TopGraphObserver. -- 7e5ae47: Teach board server to expose oauth redirect. -- f55b0f6: Implement support for simple secret provider. -- 90f1662: Teach App View about OAuth connection secrets. - -### Patch Changes - -- 927cb32: Add a margin to the newest edge entry in the app view -- 703f17d: Various fixes to make board server work again. -- e543b2e: Unbreak the app view and only store top graph edge values. -- f10e709: Update build deps. -- 1f4ced4: Don't display title when the graph is title-less. -- 19ae55b: Teach board server node proxy about data store groups. -- 41122ea: Show the actual title, not just "true" in App View. -- Updated dependencies [703f17d] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [4dadf16] -- Updated dependencies [8f9fddf] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [9797718] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [a039d2e] -- Updated dependencies [9783ba8] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [d7606d3] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] - - @google-labs/breadboard@0.27.0 - - @breadboard-ai/data-store@0.2.3 - -## 0.6.0 - -### Minor Changes - -- 7d46a63: Teach Visual Editor to use board server's node proxy to run boards. -- b11e1b8: Supply an image for the Open Graph card. -- 109a0af: Adds SQLite storage backend and adds 500 responses for errors -- 8be43c7: Configure allowed origins from environment var instead of Firestore -- 2d71df5: Teach dockerfile about firestore build and slim down the build process. - -### Patch Changes - -- Updated dependencies [7d46a63] - - @google-labs/breadboard@0.26.0 - - @breadboard-ai/data-store@0.2.2 - -## 0.5.0 - -### Minor Changes - -- cacd8e2: Introduce HTML preview for llm-output. -- 8b86be4: Support Google Cloud Run deployment. -- e0dccfe: Polish app view. -- dd34aba: Introduce social media previews for board server app view. -- f6c6378: Remove auto-sign-in machinery (it can't work as designed) -- 068e8cb: Introduce the invite links system for board server. -- 836058f: Teach App view to handle multimodal content. -- 001b250: Add support for unclamped outputs -- b201e07: Implement edge-based UI in board-server (and fix a bunch of bugs elsewhere) -- 15b5659: Teach app view to use RemoteRunner. -- a34bb69: Introduce RemoteRunner (over HTTPS) -- 34bcd9d: Auto-start board run in app view. -- e0d5971: Teach App view to stop/restart gracefully. -- 28895c3: Add support for inline controls -- 7de241c: Remove `BoardRunner`. -- a424c92: Teach remote runner to send fewer bytes over the wire. -- 79d709c: Introduce Edge event to Local and Remote runners. -- ed9ea27: Update .app endpoint - -### Patch Changes - -- 99510ae: Tweaks to .app UI -- 1ca21a5: [board-server] Refactor server startup -- b897c58: [board-server] Read allowed origins env variable -- 1683b5a: Add invites and toasts -- 4d04a01: Add support for deleting an invite -- 28089f1: Add new files to build set -- e292715: Add proper MIME types for CSS and JS -- 2309b88: Add date & time to event header -- c170348: Various bug fixes. -- cb01b95: Add a rudimentary home page. -- 3b73763: Fix a bug where visitor state raced with auto-run. -- 1c7e83c: Add support for running remote/local -- 4db8fc4: Animate the entries coming in a little -- d799af1: Apply some polish to .app view -- 6105d6e: Improve keyboard support for modals -- 61bace9: Check for the empty object when supplying inputs. -- 7350e8b: Register even more MIME types. -- c2cd40d: Add InspectableRunEdgeEvent -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @google-labs/breadboard@0.25.0 - - @breadboard-ai/data-store@0.2.1 - -## 0.4.0 - -### Minor Changes - -- bbf2c30: Plumb interruptible run to board server. -- 9b22cab: Implement the `run` API endpoint. -- 3f8cdd1: Introduce run store - -### Patch Changes - -- f27acdf: Fix build error. -- 1dc645a: Add a (failing so far) test for bubbling inputs from invoke. -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [1dc645a] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [c04cff0] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - - @breadboard-ai/data-store@0.2.0 - -## 0.3.0 - -### Minor Changes - -- 1e1be2a: Teach board-server run API endpoint to run simple boards. -- 7298a47: Add simple BSE endpoint to boards. -- 1b17915: Start laying down infrastructure for `run` API endpoint. -- 2b9ef5b: Rewrire Datastore usage -- 08a4c24: Lock BSE endpoints behind a key. -- 6ffa89c: Migrate to new data-store package - -### Patch Changes - -- Updated dependencies [1e1be2a] -- Updated dependencies [2b094a3] -- Updated dependencies [fa93c3f] -- Updated dependencies [215bd15] -- Updated dependencies [2b9ef5b] -- Updated dependencies [a0852df] -- Updated dependencies [5ce1026] -- Updated dependencies [2312443] -- Updated dependencies [6ffa89c] - - @google-labs/breadboard@0.23.0 - - @breadboard-ai/data-store@0.1.0 - -## 0.2.0 - -### Minor Changes - -- 6f82dea: Update Visual Editor package name -- 0f9d617: Move breadboard-web to visual-editor; remove breadbuddy -- 4311bd4: Ensure that proxy endpoint uses the same rules as board server. - -### Patch Changes - -- 77fd526: Update board-server README -- 501c868: Fix an off-by-one slice error. -- f4397b9: Update remaining breadboard-web paths -- Updated dependencies [a925cf0] -- Updated dependencies [5cf08f1] -- Updated dependencies [ffbf163] -- Updated dependencies [8928fb7] -- Updated dependencies [d6706f2] -- Updated dependencies [5447426] -- Updated dependencies [7e1f01c] - - @google-labs/breadboard@0.22.0 - -## 0.1.0 - -### Minor Changes - -- 345738d: Implement auth support for board server. -- 417323c: Teach Board Server to use Node Proxy Server -- 2e09278: Teach board server to tell a bit about itself. -- bcfba50: Add App View to Board Server -- 631babd: Make board server deployable in more environments. -- e7147ff: Introduce Board Server. -- 714a536: A working sketch of a server. -- 3e3fcc6: Teach board server to find unique names for boards. -- 891d022: Teach board server to send username and board tags. -- c86e648: Teach board-server about vitejs. -- 225c7cc: Implement simple ACL for board server. -- 511bd9b: Add support for `published`, `title`, and `mine` metadata for board server. -- d419142: Use esbuild for building the server bits to allow bundling Breadboard in. - -### Patch Changes - -- ffe280f: Teach board-server to add accounts. -- 43648aa: Clean up board-server API logic. -- 2be1c4a: Create API Explorer Endpoint Placeholder -- 89dcc4f: Adds board server API key to first run -- 25064e7: Create new RunObserver on loads -- 7725341: Teach board server about `.app`. -- c80aa62: Better README. -- Updated dependencies [5a55b7d] -- Updated dependencies [f4c9d36] -- Updated dependencies [7dd8fee] -- Updated dependencies [74ade20] -- Updated dependencies [2e023b8] -- Updated dependencies [59dd0f5] -- Updated dependencies [345738d] -- Updated dependencies [417323c] -- Updated dependencies [3d5ae56] -- Updated dependencies [b3aa884] -- Updated dependencies [dfc6054] -- Updated dependencies [57e8714] -- Updated dependencies [3d7b4a7] -- Updated dependencies [7af14cf] -- Updated dependencies [bcfba50] -- Updated dependencies [0a9769b] -- Updated dependencies [9c97650] -- Updated dependencies [608edac] -- Updated dependencies [5a55b7d] -- Updated dependencies [fea8967] -- Updated dependencies [631babd] -- Updated dependencies [778f7aa] -- Updated dependencies [808f5e2] -- Updated dependencies [d131307] -- Updated dependencies [499eac0] -- Updated dependencies [00746bb] -- Updated dependencies [726d38e] -- Updated dependencies [e0fdbc3] -- Updated dependencies [83ed3b5] -- Updated dependencies [54b03b9] -- Updated dependencies [810d7fd] -- Updated dependencies [14853d5] -- Updated dependencies [714a536] -- Updated dependencies [8798514] -- Updated dependencies [eb64b9a] -- Updated dependencies [cf17933] -- Updated dependencies [1f7e37d] -- Updated dependencies [bfa65a3] -- Updated dependencies [3ab7a87] -- Updated dependencies [431fa3d] -- Updated dependencies [ef86632] -- Updated dependencies [8c90376] -- Updated dependencies [32a48a3] -- Updated dependencies [4db3ab7] -- Updated dependencies [cd73b17] -- Updated dependencies [81d82fe] -- Updated dependencies [537d9f9] -- Updated dependencies [2a7531b] -- Updated dependencies [8ec03e0] -- Updated dependencies [2e3f555] -- Updated dependencies [7c1b4cb] -- Updated dependencies [702cfe1] -- Updated dependencies [a5898df] -- Updated dependencies [bebd96e] -- Updated dependencies [91cb723] -- Updated dependencies [3e10f0f] -- Updated dependencies [c53ca01] -- Updated dependencies [4c681cb] -- Updated dependencies [fb2e584] -- Updated dependencies [9491266] -- Updated dependencies [2ace620] -- Updated dependencies [fcef799] -- Updated dependencies [08c999a] -- Updated dependencies [37418d9] -- Updated dependencies [083f69c] -- Updated dependencies [c03173d] -- Updated dependencies [d6867c0] -- Updated dependencies [8dbb1cf] -- Updated dependencies [d1a9d8a] -- Updated dependencies [5b03d96] -- Updated dependencies [f0d8d67] -- Updated dependencies [836389d] -- Updated dependencies [225c7cc] -- Updated dependencies [546752d] -- Updated dependencies [009e0ea] -- Updated dependencies [7429050] -- Updated dependencies [331d4b5] - - @google-labs/breadboard-web@1.10.0 - - @google-labs/breadboard@0.21.0 diff --git a/packages/board-server/Dockerfile b/packages/board-server/Dockerfile deleted file mode 100644 index 6d2267f5639..00000000000 --- a/packages/board-server/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Build stage -FROM node:20-slim AS build -WORKDIR /build - -# Copy the entire monorepo -COPY --from=breadboard / ./ - -# Install ALL dependencies, including devDependencies -RUN npm ci - -# Build the project -WORKDIR /build/packages/board-server -RUN npm run build - -# Production stage -FROM node:20-slim - -ARG STORAGE_BACKEND -ARG ALLOWED_ORIGINS="" - -ENV NODE_ENV=production -ENV STORAGE_BACKEND="${STORAGE_BACKEND}" -ENV ALLOWED_ORIGINS="${ALLOWED_ORIGINS}" - -WORKDIR /app - -# Copy necessary files from the build stage -COPY --from=build /build/packages/board-server/dist ./dist -COPY --from=build /build/packages/board-server/src ./src -COPY --from=build /build/packages/board-server/package.json ./ -COPY --from=build /build/packages/board-server/public ./public -COPY --from=build /build/packages/board-server/scripts ./scripts - -# Install production dependencies and tsx -RUN npm install --only=production && \ - npm install -g tsx - -EXPOSE 3000 -CMD ["node", "dist/server/index.js", "--host=0.0.0.0" ] \ No newline at end of file diff --git a/packages/board-server/README.md b/packages/board-server/README.md deleted file mode 100644 index 40d10c48004..00000000000 --- a/packages/board-server/README.md +++ /dev/null @@ -1,189 +0,0 @@ -# Breadboard Board Server Reference Implementation - -## Running tests - -To run the tests: - -``` -npm run test -npm run test:integration -``` - -## Choosing a storage backend - -The board server can be run with different storage backends. The default is `firestore`, but you can also run it with `sqlite`. - -To run locally with `sqlite`: - -``` -export GOOGLE_APPLICATION_CREDENTIALS=n/a -export STORAGE_BACKEND=sqlite -export SQLITE_DB_PATH=/path/to/board-server.db -``` - -## Building with docker - -The board server can be run as a self-contained docker image. - -To build the container with the `sqlite` backend: - -``` -docker build --build-arg STORAGE_BACKEND=sqlite --build-context breadboard=../../ -t board-server:sqlite . -``` - -This container will use `sqlite` as a storage backend. It will keep its state in a file called `board-server.db` inside the working directory on the container. - -To build the container with the `firestore` backend: - -``` -docker build --build-arg STORAGE_BACKEND=firestore --build-context breadboard=../../ -t board-server:firestore . -``` - -This container will use `firestore` backend and connect to Google Cloud Firestore database. - -More than likely, in either case you will want to specify the `ALLOWED_ORIGINS` build argument: - -```sh -docker build --build-arg ALLOWED_ORIGINS="list of visual editor urls" ...` -``` - -When building on Apple Silicon, use `platform` flag to specify the right platform: - -```sh -docker build --platform linux/amd64 ... -``` - -To run the container: - -``` -docker run -d -p 3000:3000 --name board-server board-server -docker exec -it board-server /bin/bash -# npm run add # add a user and copy your API key -``` - -## Deploying container on Cloud Run - -[Create repository](https://cloud.google.com/artifact-registry/docs/repositories/create-repos#create-console) - -Run credential helper: - -```sh - gcloud auth configure-docker us-central1-docker.pkg.dev -``` - -Get the full image name. See [Tagging the local image](https://cloud.google.com/artifact-registry/docs/docker/pushing-and-pulling#tag) for details. - -Tag the local image with the repository name: - -```sh -docker tag source-image image-name -``` - -Push image to repository - -```sh -docker push image-name -``` - -Deploy to Cloud Run: - -```sh -gcloud run deploy service-name --image image-name -``` - -## Firestore & App Engine deployment - -Uses Firestore. Deploys to App Engine. - -You will need to get ADC going to make Firestore work: - -One-time setup: - -- Login - -```bash -gcloud auth login -``` - -```bash -gcloud auth application-default login -``` - -```bash -gcloud config set project -``` - -- Create App Engine App in Cloud Console - -- [Enable Firestore API](https://console.cloud.google.com/marketplace/product/google/firestore.googleapis.com) - -- [Create Firestore database](https://console.cloud.google.com/firestore/databases) named "board-server" - -Then, to run locally, from the root of the repo: - -```bash -npm run s -``` - -This will bring up the board server at `http://localhost:3000` and -a breadboard-web dev server at whatever port it launches (usually `http://localhost:5173/`). - -To deploy: - -```bash -npm run deploy -``` - -This will build the project and deploy it to App Engine. - -## Using secrets - -If you wish to run boards on the server, you will need to store secrets on the board server. - -Currently, there are two choices: using [Google Cloud Secret Manager](https://cloud.google.com/security/products/secret-manager?hl=en) and using the `secrets.json` file. - -The choice is based on the value of the `STORAGE_BACKEND` variable. - -If the value is `sqlite`, the `secrets.json` file will be used to retrieve the secrets. - -If the value is `firestore`, the Google Cloud Secret Manager will be used. - -Each secret must contain three pieces of information: - -- **name**, such as `GEMINI_KEY`. This name should match the key that the boards use to ask for this secret. - -- **value** -- the value of the secret. - -- **origin** -- the associated [origin](https://developer.mozilla.org/en-US/docs/Glossary/Origin) of the key. The secrets are most often used to gain access to various service APIs. To ensure that only those services can see their secret, the secrets are bound to the origin of the service. - -### Storing secrets with `secrets.json` - -At the root of the repository, place the file named `secrets.json`. - -The file format is as follows: - -```json -{ - "SECRET_NAME_GOES_HERE": { - "secret": "SECRET_VALUE_GOES_HERE", - "origin": "origin/of/secret/consumer/goes/here" - } -} -``` - -For example: - -```json -{ - "GEMINI_KEY": { - "secret": " ...value elided..", - "origin": "https://generativelanguage.googleapis.com" - } -} -``` - -### Storing secrets with Google Cloud Secret Manager - -Store secrets in the Secret Manager per [GCP docs](https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets). - -For each secret, add annotation named `origin` to specify the origin of secret consumer. diff --git a/packages/board-server/api.html b/packages/board-server/api.html deleted file mode 100644 index ef468aacd91..00000000000 --- a/packages/board-server/api.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - API - - - - - - - diff --git a/packages/board-server/app.yaml b/packages/board-server/app.yaml deleted file mode 100644 index 93a695f9367..00000000000 --- a/packages/board-server/app.yaml +++ /dev/null @@ -1,17 +0,0 @@ -runtime: nodejs22 - -instance_class: F2 - -handlers: - - url: /boards.* - script: auto - - - url: /(.*\..+)$ - static_files: dist/client/\1 - upload: dist/client/(.*\..+)$ - -env_variables: - ALLOWED_ORIGINS: "" - -build_env_variables: - GOOGLE_NODE_RUN_SCRIPTS: "" diff --git a/packages/board-server/index.html b/packages/board-server/index.html deleted file mode 100644 index d40be79ee7a..00000000000 --- a/packages/board-server/index.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - Breadboard App View - Loading - - - - - - - - - - - - - - - - diff --git a/packages/board-server/oauth/index.html b/packages/board-server/oauth/index.html deleted file mode 100644 index 6badd6a4e2e..00000000000 --- a/packages/board-server/oauth/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - Redirecting ... - - - - - diff --git a/packages/board-server/openapi.yaml b/packages/board-server/openapi.yaml deleted file mode 100644 index 04c51bfc4dc..00000000000 --- a/packages/board-server/openapi.yaml +++ /dev/null @@ -1,484 +0,0 @@ -openapi: 3.1.0 -info: - title: Board Server API - version: 1.0.0 - description: API for managing and interacting with boards - -servers: - - url: http://localhost:3000 - -paths: - /boards: - get: - summary: List boards - operationId: boardserver.boards.list - security: [] - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/BoardListEntry' - - /boards/@{account}/{boardName}.json: - get: - summary: Get a board - operationId: boardserver.boards.get - security: [] - parameters: - - $ref: '#/components/parameters/AccountParam' - - $ref: '#/components/parameters/BoardNameParam' - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/Board' - - post: - summary: Create or update a board - operationId: boardserver.boards.post - security: [] - parameters: - - $ref: '#/components/parameters/AccountParam' - - $ref: '#/components/parameters/BoardNameParam' - - $ref: '#/components/parameters/ApiKeyQuery' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Board' - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - created: - type: string - - /boards/@{account}/{boardName}.app: - get: - summary: Serve frontend app - operationId: boardserver.boards.serve - security: [] - parameters: - - $ref: '#/components/parameters/AccountParam' - - $ref: '#/components/parameters/BoardNameParam' - responses: - '200': - description: Successful response - content: - text/html: - schema: - type: string - - /boards/@{account}/{boardName}.api: - get: - summary: Serve API explorer - operationId: boardserver.boards.api.get - security: [] - parameters: - - $ref: '#/components/parameters/AccountParam' - - $ref: '#/components/parameters/BoardNameParam' - responses: - '200': - description: Successful response - content: - text/html: - schema: - type: string - - /boards/@{account}/{boardName}.api/invoke: - post: - summary: Invoke API - operationId: boardserver.boards.api.invoke - security: [] - parameters: - - $ref: '#/components/parameters/AccountParam' - - $ref: '#/components/parameters/BoardNameParam' - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - $key: - type: string - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - - /boards/@{account}/{boardName}.api/describe: - post: - summary: Get API description - operationId: boardserver.boards.api.describe - security: [] - parameters: - - $ref: '#/components/parameters/AccountParam' - - $ref: '#/components/parameters/BoardNameParam' - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/ApiDescription' - - /boards/@{account}/{boardName}.api/run: - post: - summary: Execute the board - operationId: boardserver.boards.api.run - security: [] - parameters: - - $ref: '#/components/parameters/AccountParam' - - $ref: '#/components/parameters/BoardNameParam' - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - $key: - type: string - responses: - '200': - description: Successful response - content: - text/event-stream: - schema: - type: string - - /boards/@{account}/{boardName}.invite: - get: - summary: List invites - operationId: boardserver.boards.invite - security: [] - parameters: - - $ref: '#/components/parameters/AccountParam' - - $ref: '#/components/parameters/BoardNameParam' - - $ref: '#/components/parameters/ApiKeyQuery' - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: object - properties: - invites: - type: array - items: - type: string - - post: - summary: Create or delete an invite - operationId: boardserver.boards.invites.post - security: [] - parameters: - - $ref: '#/components/parameters/AccountParam' - - $ref: '#/components/parameters/BoardNameParam' - - $ref: '#/components/parameters/ApiKeyQuery' - requestBody: - content: - application/json: - schema: - type: object - properties: - delete: - type: string - responses: - '200': - description: Successful response - content: - application/json: - schema: - oneOf: - - type: object - properties: - invite: - type: string - - type: object - properties: - deleted: - type: string - - type: object - properties: - error: - type: string - -components: - parameters: - AccountParam: - name: account - in: path - required: true - schema: - type: string - BoardNameParam: - name: boardName - in: path - required: true - schema: - type: string - ApiKeyQuery: - name: API_KEY - in: query - required: true - schema: - type: string - - schemas: - BoardListEntry: - type: object - properties: - title: - type: string - path: - type: string - username: - type: string - readonly: - type: boolean - mine: - type: boolean - tags: - type: array - items: - type: string - - Board: - type: object - properties: - url: - type: string - title: - type: string - description: - type: string - version: - type: string - edges: - type: array - items: - $ref: '#/components/schemas/Edge' - nodes: - type: array - items: - $ref: '#/components/schemas/Node' - kits: - type: array - items: - type: object - properties: - url: - type: string - title: - type: string - description: - type: string - version: - type: string - tags: - type: array - items: - type: string - enum: - - deprecated - - experimental - required: - - url - graphs: - type: object - additionalProperties: - $ref: '#/components/schemas/Board' - args: - type: object - additionalProperties: true - required: - - nodes - - edges - - NodeMetaData: - type: object - properties: - title: - type: string - description: - type: string - visual: - type: object - additionalProperties: true - logLevel: - type: string - enum: - - debug - - info - tags: - type: array - items: - oneOf: - - type: string - enum: - - start - - $ref: '#/components/schemas/StartTag' - - Node: - type: array - items: - type: object - properties: - id: - type: string - type: - type: string - configuration: - type: object - additionalProperties: true - metadata: - $ref: '#/components/schemas/NodeMetaData' - required: - - id - - type - - StartTag: - type: object - properties: - type: - type: string - label: - $ref: '#/components/schemas/StartLabel' - required: - - type - - StartLabel: - type: string - enum: - - default - - describe - - Edge: - type: array - items: - type: object - properties: - from: - type: string - to: - type: string - in: - type: string - out: - type: string - optional: - type: boolean - constant: - type: boolean - required: - - from - - to - - Schema: - type: object - properties: - title: - type: string - description: - type: string - type: - oneOf: - - type: string - - type: array - items: - type: string - properties: - type: object - additionalProperties: - $ref: '#/components/schemas/Schema' - required: - type: array - items: - type: string - format: - type: string - behavior: - type: string - enum: - - deprecated - - transient - - bubble - - board - - stream - - error - - config - - llm-content - - json-schema - - ports-spec - - image - - code - - google-drive-query - - google-drive-file-id - transient: - type: boolean - enum: - type: array - items: - type: string - default: - type: string - additionalProperties: - oneOf: - - type: boolean - - $ref: '#/components/schemas/Schema' - items: - oneOf: - - $ref: '#/components/schemas/Schema' - - type: array - items: - $ref: '#/components/schemas/Schema' - minItems: - type: number - examples: - type: array - items: - type: string - - ApiDescription: - type: object - properties: - inputSchema: - type: object - outputSchema: - type: object - title: - type: string - description: - type: string - metadata: - type: object - properties: - icon: - type: string - comments: - type: object - properties: - id: - type: string - text: - type: string - metadata: - $ref: '#/components/schemas/NodeMetaData' - additionalProperties: true diff --git a/packages/board-server/package.json b/packages/board-server/package.json deleted file mode 100644 index fc3958f2ccb..00000000000 --- a/packages/board-server/package.json +++ /dev/null @@ -1,195 +0,0 @@ -{ - "name": "@breadboard-ai/board-server", - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "private": true, - "version": "0.7.0", - "description": "Board Server", - "main": "./dist/server/index.js", - "exports": "./dist/server/index.js", - "type": "module", - "scripts": { - "start": "node .", - "prepack": "npm run build", - "build": "wireit", - "build:vite": "wireit", - "build:esbuild": "wireit", - "build:docker": "docker build --build-context breadboard=../../ -t board-server .", - "deploy": "npm run build && gcloud app deploy", - "deploy:gcr": "npm run build && gcloud run deploy --source .", - "add": "tsx scripts/create-account.ts", - "serve": "wireit", - "dev": "npm run dev:nowatch --watch", - "dev:nowatch": "wireit", - "test": "wireit", - "test:integration": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "build:vite", - "build:esbuild" - ] - }, - "build:vite": { - "command": "vite build", - "files": [ - "*.html", - "vite.config.ts", - "package.json", - "src/app/**/*.ts", - ".env.development", - ".env.production" - ], - "output": [ - "dist/client" - ], - "dependencies": [ - "build:esbuild", - "../breadboard:build:tsc", - "../data-store:build:tsc", - "../agent-kit:build:tsc", - "../palm-kit:build:tsc", - "../core-kit:build:tsc", - "../json-kit:build:tsc", - "../template-kit:build:tsc", - "../node-nursery-web:build:tsc", - "../shared-ui:build:tsc" - ], - "clean": "if-file-deleted" - }, - "build:esbuild": { - "command": "tsx scripts/build.ts", - "files": [ - "scripts/build.ts", - "src/index.ts", - "src/router.ts", - "src/server.ts", - "src/server/**/*.ts", - "tsconfig.json", - "package.json" - ], - "output": [ - "dist/server/index.js" - ], - "dependencies": [ - "../breadboard:build", - "../data-store:build", - "../agent-kit:build", - "../palm-kit:build", - "../core-kit:build", - "../json-kit:build", - "../template-kit:build", - "../node-nursery-web:build" - ], - "clean": "if-file-deleted" - }, - "serve": { - "service": true, - "command": "node .", - "dependencies": [ - "build" - ] - }, - "dev:nowatch": { - "command": "export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project) && node .", - "service": true, - "env": { - "ALLOWED_ORIGINS": "http://localhost:5173" - }, - "dependencies": [ - "build", - { - "script": "../visual-editor:serve", - "cascade": false - } - ] - }, - "build:tests": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "../breadboard:build:tsc", - "../data-store:build:tsc", - "../agent-kit:build:tsc", - "../palm-kit:build:tsc", - "../core-kit:build:tsc", - "../json-kit:build:tsc", - "../template-kit:build:tsc", - "../node-nursery-web:build:tsc", - "../shared-ui:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tests/**/*.ts", - "tests/*.json", - "tests/boards/*.bgl.json", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "clear:testdb": { - "command": "rm -f test.db" - }, - "test": { - "command": "node --test --enable-source-maps --test-reporter spec dist/tests/*.js", - "dependencies": [ - "build:tests" - ], - "files": [], - "output": [] - }, - "test:integration": { - "command": "export GOOGLE_APPLICATION_CREDENTIALS=foo && export GOOGLE_CLOUD_PROJECT=foo && export STORAGE_BACKEND=sqlite && export SQLITE_DB_PATH=test.db && node --test --enable-source-maps --test-reporter spec dist/tests/integration/board-api.test.js", - "dependencies": [ - "build:tests", - "build:vite", - "clear:testdb" - ], - "files": [], - "output": [] - } - }, - "repository": { - "directory": "packages/board-server", - "type": "git", - "url": "https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src" - ], - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard#readme", - "devDependencies": { - "@types/better-sqlite3": "^7.6.11", - "@types/node": "^22.0.0", - "@types/uuid": "^10.0.0", - "esbuild": "^0.24.0", - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" - }, - "dependencies": { - "@breadboard-ai/data-store": "^0.2.3", - "@google-cloud/firestore": "^7.10.0", - "@google-cloud/secret-manager": "^5.6.0", - "@google-labs/breadboard": "^0.27.0", - "@lit/context": "^1.1.2", - "better-sqlite3": "^11.3.0", - "lit": "^3.2.0", - "uuid": "^10.0.0", - "vite": "^5.4.8" - } -} diff --git a/packages/board-server/project.toml b/packages/board-server/project.toml deleted file mode 100644 index 78073ec245f..00000000000 --- a/packages/board-server/project.toml +++ /dev/null @@ -1,3 +0,0 @@ -[[build.env]] -name = "GOOGLE_NODE_RUN_SCRIPTS" -value = "" \ No newline at end of file diff --git a/packages/board-server/public/images/og-image.png b/packages/board-server/public/images/og-image.png deleted file mode 100644 index c151155ad4e..00000000000 Binary files a/packages/board-server/public/images/og-image.png and /dev/null differ diff --git a/packages/board-server/public/images/progress-ui.svg b/packages/board-server/public/images/progress-ui.svg deleted file mode 100644 index 2b5534a263c..00000000000 --- a/packages/board-server/public/images/progress-ui.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/packages/board-server/public/images/progress.svg b/packages/board-server/public/images/progress.svg deleted file mode 100644 index 08cb1a298de..00000000000 --- a/packages/board-server/public/images/progress.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/packages/board-server/public/kits.json b/packages/board-server/public/kits.json deleted file mode 100644 index fe51488c706..00000000000 --- a/packages/board-server/public/kits.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/packages/board-server/public/styles/api-view.css b/packages/board-server/public/styles/api-view.css deleted file mode 100644 index 8956a688f19..00000000000 --- a/packages/board-server/public/styles/api-view.css +++ /dev/null @@ -1,157 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -* { - box-sizing: border-box; -} - -:root { - --bb-grid-size: 4px; - --bb-grid-size-2: calc(var(--bb-grid-size) * 2); - --bb-grid-size-3: calc(var(--bb-grid-size) * 3); - --bb-grid-size-4: calc(var(--bb-grid-size) * 4); - --bb-grid-size-5: calc(var(--bb-grid-size) * 5); - --bb-grid-size-6: calc(var(--bb-grid-size) * 6); - --bb-grid-size-7: calc(var(--bb-grid-size) * 7); - --bb-grid-size-8: calc(var(--bb-grid-size) * 8); - --bb-grid-size-9: calc(var(--bb-grid-size) * 9); - --bb-grid-size-10: calc(var(--bb-grid-size) * 10); - --bb-grid-size-11: calc(var(--bb-grid-size) * 11); - --bb-grid-size-12: calc(var(--bb-grid-size) * 12); - --bb-grid-size-13: calc(var(--bb-grid-size) * 13); - --bb-grid-size-14: calc(var(--bb-grid-size) * 14); - --bb-grid-size-15: calc(var(--bb-grid-size) * 15); - --bb-grid-size-16: calc(var(--bb-grid-size) * 16); - - --bb-font-family-header: "Fira Code"; - --bb-font-family-mono: "Fira Code", "Courier New", Courier, monospace; - --bb-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - - --bb-icon-collapse-inverted: url(/third_party/icons/collapse-inverted.svg); - --bb-icon-expand-inverted: url(/third_party/icons/expand-inverted.svg); - --bb-icon-menu: url(/third_party/icons/menu.svg); - --bb-icon-search-inverted: url(/third_party/icons/search-inverted.svg); - --bb-icon-smart-toy-inverted: url(/third_party/icons/smart-toy-inverted.svg); - - --bb-warning-50: #ffffff; - --bb-warning-100: #ffcccc; - --bb-warning-200: #ff9999; - --bb-warning-300: #ff6666; - --bb-warning-400: #ff3333; - --bb-warning-500: #ff0000; - --bb-warning-600: #cc0000; - --bb-warning-700: #990000; - --bb-warning-800: #660000; - --bb-warning-900: #330000; - - --bb-inputs-50: #eaf7e7; - --bb-inputs-100: #bbe7b0; - --bb-inputs-200: #9adc8a; - --bb-inputs-300: #6ccb55; - --bb-inputs-400: #4fc134; - --bb-inputs-500: #24b202; - --bb-inputs-600: #20a202; - --bb-inputs-700: #1a7e01; - --bb-inputs-800: #136202; - --bb-inputs-900: #0f4b00; - - --bb-nodes-50: #fff9e6; - --bb-nodes-100: #ffebb0; - --bb-nodes-200: #ffe28b; - --bb-nodes-300: #ffd454; - --bb-nodes-400: #ffcc33; - --bb-nodes-500: #ffbf00; - --bb-nodes-600: #e8af02; - --bb-nodes-700: #b68902; - --bb-nodes-800: #8c6900; - --bb-nodes-900: #6b5000; - - --bb-boards-50: #fff4eb; - --bb-boards-100: #ffdfc0; - --bb-boards-200: #ffcea1; - --bb-boards-300: #feb876; - --bb-boards-400: #feab5c; - --bb-boards-500: #fe9533; - --bb-boards-600: #e7882e; - --bb-boards-700: #b46b24; - --bb-boards-800: #8c521b; - --bb-boards-900: #6b3f15; - - --bb-ui-50: #ecf5ff; - --bb-ui-100: #c0dfff; - --bb-ui-200: #a1d0ff; - --bb-ui-300: #77bbff; - --bb-ui-400: #5cadff; - --bb-ui-500: #3399ff; - --bb-ui-600: #2e8be8; - --bb-ui-700: #246db5; - --bb-ui-800: #1b548c; - --bb-ui-900: #1b548c; - - --bb-neutral-0: #ffffff; - --bb-neutral-10: #fafafa; - --bb-neutral-50: #f6f6f6; - --bb-neutral-100: #ededed; - --bb-neutral-200: #e3e3e3; - --bb-neutral-300: #d9d9d9; - --bb-neutral-400: #c2c2c2; - --bb-neutral-500: #9c9c9c; - --bb-neutral-600: #7a7a7a; - --bb-neutral-700: #595959; - --bb-neutral-800: #333333; - --bb-neutral-900: #1a1a1a; - - --bb-title-large: 22px; - --bb-title-line-height-large: 28px; - - --bb-title-medium: 16px; - --bb-title-line-height-medium: 24px; - - --bb-title-small: 14px; - --bb-title-line-height-small: 20px; - - --bb-label-large: 14px; - --bb-label-line-height-large: 20px; - - --bb-label-medium: 12px; - --bb-label-line-height-medium: 16px; - - --bb-label-small: 11px; - --bb-label-line-height-small: 16px; - - --bb-body-large: 16px; - --bb-body-line-height-large: 24px; - - --bb-body-medium: 14px; - --bb-body-line-height-medium: 20px; - - --bb-body-small: 12px; - --bb-body-line-height-small: 16px; - - --bb-body-x-small: 10px; - --bb-body-line-height-x-small: 13px; - - /** Depth Colors */ - --bb-depth-1: hsl(48deg, 60%, 98%); - --bb-depth-2: hsl(45deg, 60%, 96%); - --bb-depth-3: hsl(42deg, 60%, 94%); - --bb-depth-4: hsl(39deg, 60%, 92%); - --bb-depth-5: hsl(36deg, 60%, 90%); -} - -html, -body { - overscroll-behavior: none; - padding: 0; - margin: 0; - font-family: var(--bb-font-family); - color: var(--bb-neutral-0); - width: 100vw; - height: 100svh; - display: flex; - flex-direction: column; - background: var(--bb-neutral-700); -} diff --git a/packages/board-server/public/styles/global.css b/packages/board-server/public/styles/global.css deleted file mode 100644 index 21226846712..00000000000 --- a/packages/board-server/public/styles/global.css +++ /dev/null @@ -1,285 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -* { - box-sizing: border-box; -} - -:root { - --bb-grid-size: 4px; - --bb-grid-size-2: calc(var(--bb-grid-size) * 2); - --bb-grid-size-3: calc(var(--bb-grid-size) * 3); - --bb-grid-size-4: calc(var(--bb-grid-size) * 4); - --bb-grid-size-5: calc(var(--bb-grid-size) * 5); - --bb-grid-size-6: calc(var(--bb-grid-size) * 6); - --bb-grid-size-7: calc(var(--bb-grid-size) * 7); - --bb-grid-size-8: calc(var(--bb-grid-size) * 8); - --bb-grid-size-9: calc(var(--bb-grid-size) * 9); - --bb-grid-size-10: calc(var(--bb-grid-size) * 10); - --bb-grid-size-11: calc(var(--bb-grid-size) * 11); - --bb-grid-size-12: calc(var(--bb-grid-size) * 12); - --bb-grid-size-13: calc(var(--bb-grid-size) * 13); - --bb-grid-size-14: calc(var(--bb-grid-size) * 14); - --bb-grid-size-15: calc(var(--bb-grid-size) * 15); - --bb-grid-size-16: calc(var(--bb-grid-size) * 16); - - --bb-selected-color: rgb(46, 139, 232); - --bb-continue-color: #c0dfff; - --bb-font-family-header: "Fira Code"; - --bb-font-family-mono: "Fira Code", "Courier New", Courier, monospace; - --bb-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - --bb-font-color: rgb(23, 23, 23); - --bb-font-color-faded: rgb(59, 59, 59); - --bb-warning-color: rgb(251, 137, 3); - --bb-error-color: rgb(251, 3, 3); - --bb-output-color: rgb(51, 235, 168); - --bb-done-color: rgb(3, 190, 122); - --bb-text-default: 1rem; - --bb-text-medium: 0.875rem; - --bb-text-small: 0.75rem; - --bb-text-nano: 0.7rem; - --bb-text-pico: 0.65rem; - --bb-easing: cubic-bezier(0, 0, 0.3, 1); - --bb-easing-duration-in: 0.15s; - --bb-easing-duration-out: 0.3s; - - --bb-icon-add: url(/third_party/icons/add.svg); - --bb-icon-add-inverted: url(/third_party/icons/add-inverted.svg); - --bb-icon-add-audio: url(/third_party/icons/add-audio.svg); - --bb-icon-add-circle: url(/third_party/icons/add-circle.svg); - --bb-icon-add-drawable: url(/third_party/icons/add-drawable.svg); - --bb-icon-add-file: url(/third_party/icons/add-file.svg); - --bb-icon-add-image-webcam: url(/third_party/icons/add-image-webcam.svg); - --bb-icon-add-image: url(/third_party/icons/add-image.svg); - --bb-icon-add-text: url(/third_party/icons/add-text.svg); - --bb-icon-add-video: url(/third_party/icons/add-video.svg); - --bb-icon-arrow-right: url(/third_party/icons/arrow-right.svg); - --bb-icon-arrow-drop-down: url(/third_party/icons/arrow-drop-down.svg); - --bb-icon-before: url(/third_party/icons/before.svg); - --bb-icon-bug: url(/third_party/icons/bug.svg); - --bb-icon-close: url(/third_party/icons/close.svg); - --bb-icon-collapse: url(/third_party/icons/collapse.svg); - --bb-icon-confirm-blue: url(/third_party/icons/confirm-blue.svg); - --bb-icon-copy-to-clipboard: url(/third_party/icons/copy-to-clipboard.svg); - --bb-icon-delete: url(/third_party/icons/delete.svg); - --bb-icon-download: url(/third_party/icons/download.svg); - --bb-icon-draft: url(/third_party/icons/draft.svg); - --bb-icon-edge-connector: url(/third_party/icons/edge-connector.svg); - --bb-icon-edit: url(/third_party/icons/edit.svg); - --bb-icon-eject: url(/third_party/icons/eject.svg); - --bb-icon-error: url(/third_party/icons/error.svg); - --bb-icon-expand: url(/third_party/icons/expand.svg); - --bb-icon-experiment: url(/third_party/icons/experiment.svg); - --bb-icon-file-add: url(/third_party/icons/file-add.svg); - --bb-icon-fit: url(/third_party/icons/fit.svg); - --bb-icon-folder-managed: url(/third_party/icons/folder-managed.svg); - --bb-icon-generic-node: url(/third_party/icons/generic-node.svg); - --bb-icon-help: url(/third_party/icons/help.svg); - --bb-icon-human: url(/third_party/icons/human.svg); - --bb-icon-info: url(/third_party/icons/info.svg); - --bb-icon-input: url(/third_party/icons/input.svg); - --bb-icon-javascript: url(/third_party/icons/javascript.svg); - --bb-icon-laps: url(/third_party/icons/laps.svg); - --bb-icon-lan: url(/third_party/icons/lan.svg); - --bb-icon-lightbulb: url(/third_party/icons/lightbulb.svg); - --bb-icon-list: url(/third_party/icons/list.svg); - --bb-icon-maximize: url(/third_party/icons/maximize.svg); - --bb-icon-mic-green: url(/third_party/icons/mic-green.svg); - --bb-icon-minimize: url(/third_party/icons/minimize.svg); - --bb-icon-merge-type: url(/third_party/icons/merge-type.svg); - --bb-icon-menu: url(/third_party/icons/menu.svg); - --bb-icon-menu-inverted: url(/third_party/icons/menu-inverted.svg); - --bb-icon-model: url(/third_party/icons/model.svg); - --bb-icon-more-vert-inverted: url(/third_party/icons/more-vert-inverted.svg); - --bb-icon-move-up: url(/third_party/icons/move-up.svg); - --bb-icon-move-down: url(/third_party/icons/move-down.svg); - --bb-icon-next: url(/third_party/icons/next.svg); - --bb-icon-open-new: url(/third_party/icons/open-new.svg); - --bb-icon-output: url(/third_party/icons/output.svg); - --bb-icon-password: url(/third_party/icons/password.svg); - --bb-icon-preview: url(/third_party/icons/preview.svg); - --bb-icon-public: url(/third_party/icons/public.svg); - --bb-icon-quick-jump: url(/third_party/icons/quick-jump.svg); - --bb-icon-redo-inverted: url(/third_party/icons/redo-inverted.svg); - --bb-icon-recent: url(/third_party/icons/recent.svg); - --bb-icon-refresh: url(/third_party/icons/refresh.svg); - --bb-icon-reset-image: url(/third_party/icons/reset-image.svg); - --bb-icon-reset-nodes: url(/third_party/icons/reset-nodes.svg); - --bb-icon-resume-blue: url(/third_party/icons/resume-blue.svg); - --bb-icon-rsvp: url(/third_party/icons/rsvp.svg); - --bb-icon-save: url(/third_party/icons/save.svg); - --bb-icon-save-as: url(/third_party/icons/save-as.svg); - --bb-icon-save-inverted: url(/third_party/icons/save-inverted.svg); - --bb-icon-share: url(/third_party/icons/share.svg); - --bb-icon-search: url(/third_party/icons/search.svg); - --bb-icon-settings: url(/third_party/icons/settings.svg); - --bb-icon-settings-inverted: url(/third_party/icons/settings-inverted.svg); - --bb-icon-smart-toy: url(/third_party/icons/smart-toy.svg); - --bb-icon-sound: url(/third_party/icons/sound.svg); - --bb-icon-stop-circle: url(/third_party/icons/stop-circle.svg); - --bb-icon-toggle-on: url(/third_party/icons/toggle-on.svg); - --bb-icon-toggle-off: url(/third_party/icons/toggle-off.svg); - --bb-icon-tool: url(/third_party/icons/tool.svg); - --bb-icon-undo-inverted: url(/third_party/icons/undo-inverted.svg); - --bb-icon-unfold-less: url(/third_party/icons/unfold-less.svg); - --bb-icon-unfold-more: url(/third_party/icons/unfold-more.svg); - --bb-icon-visibility-off: url(/third_party/icons/visibility-off.svg); - --bb-icon-warning: url(/third_party/icons/warning.svg); - - --bb-icon-expand-all-48px: url(/third_party/icons/expand-all-48px.svg); - --bb-icon-arrow-down-48px: url(/third_party/icons/arrow-down-48px.svg); - - --bb-warning-50: #ffeeee; - --bb-warning-100: #ffcccc; - --bb-warning-200: #ff9999; - --bb-warning-300: #ff6666; - --bb-warning-400: #ff3333; - --bb-warning-500: #ff0000; - --bb-warning-600: #cc0000; - --bb-warning-700: #990000; - --bb-warning-800: #660000; - --bb-warning-900: #330000; - - --bb-inputs-50: #eaf7e7; - --bb-inputs-100: #bbe7b0; - --bb-inputs-200: #9adc8a; - --bb-inputs-300: #6ccb55; - --bb-inputs-400: #4fc134; - --bb-inputs-500: #24b202; - --bb-inputs-600: #20a202; - --bb-inputs-700: #1a7e01; - --bb-inputs-800: #136202; - --bb-inputs-900: #0f4b00; - - --bb-nodes-50: #fff9e6; - --bb-nodes-100: #ffebb0; - --bb-nodes-200: #ffe28b; - --bb-nodes-300: #ffd454; - --bb-nodes-400: #ffcc33; - --bb-nodes-500: #ffbf00; - --bb-nodes-600: #e8af02; - --bb-nodes-700: #b68902; - --bb-nodes-800: #8c6900; - --bb-nodes-900: #6b5000; - - --bb-boards-50: #fff4eb; - --bb-boards-100: #ffdfc0; - --bb-boards-200: #ffcea1; - --bb-boards-300: #feb876; - --bb-boards-400: #feab5c; - --bb-boards-500: #fe9533; - --bb-boards-600: #e7882e; - --bb-boards-700: #b46b24; - --bb-boards-800: #8c521b; - --bb-boards-900: #6b3f15; - - --bb-ui-50: #ecf5ff; - --bb-ui-100: #c0dfff; - --bb-ui-200: #a1d0ff; - --bb-ui-300: #77bbff; - --bb-ui-400: #5cadff; - --bb-ui-500: #3399ff; - --bb-ui-600: #2e8be8; - --bb-ui-700: #246db5; - --bb-ui-800: #1b548c; - --bb-ui-900: #1b548c; - - --bb-neutral-0: #ffffff; - --bb-neutral-10: #fafafa; - --bb-neutral-50: #f6f6f6; - --bb-neutral-100: #ededed; - --bb-neutral-200: #e3e3e3; - --bb-neutral-300: #d9d9d9; - --bb-neutral-400: #c2c2c2; - --bb-neutral-500: #9c9c9c; - --bb-neutral-600: #7a7a7a; - --bb-neutral-700: #595959; - --bb-neutral-800: #333333; - --bb-neutral-900: #1a1a1a; - - --bb-human-50: #ece7f4; - --bb-human-100: #cfc3e4; - --bb-human-200: #b19cd2; - --bb-human-300: #9274c0; - --bb-human-400: #7c56b3; - --bb-human-500: #653aa6; - --bb-human-600: #5d35a0; - --bb-human-700: #512d97; - --bb-human-800: #46278e; - --bb-human-900: #351c7f; - - --bb-looper-50: #e0f2f1; - --bb-looper-100: #b2dfdb; - --bb-looper-200: #80cbc4; - --bb-looper-300: #4db6ac; - --bb-looper-400: #26a69a; - --bb-looper-500: #009688; - --bb-looper-600: #00897b; - --bb-looper-700: #00796b; - --bb-looper-800: #00695c; - --bb-looper-900: #004d40; - - --bb-title-large: 22px; - --bb-title-line-height-large: 28px; - - --bb-title-medium: 16px; - --bb-title-line-height-medium: 24px; - - --bb-title-small: 14px; - --bb-title-line-height-small: 20px; - - --bb-label-large: 14px; - --bb-label-line-height-large: 20px; - - --bb-label-medium: 12px; - --bb-label-line-height-medium: 16px; - - --bb-label-small: 11px; - --bb-label-line-height-small: 16px; - - --bb-body-large: 16px; - --bb-body-line-height-large: 24px; - - --bb-body-medium: 14px; - --bb-body-line-height-medium: 20px; - - --bb-body-small: 12px; - --bb-body-line-height-small: 16px; - - --bb-body-x-small: 10px; - --bb-body-line-height-x-small: 13px; - - --bb-font-title-large: 400 22px/28px var(--bb-font-family); - --bb-font-title-medium: 400 16px/24px var(--bb-font-family); - --bb-font-title-small: 400 14px/20px var(--bb-font-family); - - --bb-font-label-large: 400 14px/20px var(--bb-font-family); - --bb-font-label-medium: 400 12px/16px var(--bb-font-family); - --bb-font-label-small: 400 11px/16px var(--bb-font-family); - - --bb-font-body-large: 400 16px/24px var(--bb-font-family); - --bb-font-body-medium: 400 14px/20px var(--bb-font-family); - --bb-font-body-small: 400 12px/16px var(--bb-font-family); - --bb-font-body-x-small: 400 10px/13px var(--bb-font-family); - - /** Depth Colors */ - --bb-depth-1: hsl(48deg, 60%, 98%); - --bb-depth-2: hsl(45deg, 60%, 96%); - --bb-depth-3: hsl(42deg, 60%, 94%); - --bb-depth-4: hsl(39deg, 60%, 92%); - --bb-depth-5: hsl(36deg, 60%, 90%); -} - -html, -body { - padding: 0; - margin: 0; - font-family: var(--bb-font-family); - color: var(--bb-font-color); - width: 100%; - height: 100svh; - background: var(--bb-neutral-0); -} diff --git a/packages/board-server/public/third_party/icons/README.md b/packages/board-server/public/third_party/icons/README.md deleted file mode 100644 index 88fe3514da1..00000000000 --- a/packages/board-server/public/third_party/icons/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Icons - -These icons are from [Material Design Icons](https://fonts.google.com/icons), and are licensed under [Apache 2.0](https://github.com/google/material-design-icons/blob/master/LICENSE). diff --git a/packages/board-server/public/third_party/icons/add-audio.svg b/packages/board-server/public/third_party/icons/add-audio.svg deleted file mode 100644 index b110e9108a0..00000000000 --- a/packages/board-server/public/third_party/icons/add-audio.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/add-circle.svg b/packages/board-server/public/third_party/icons/add-circle.svg deleted file mode 100644 index 8e8a1caaa8d..00000000000 --- a/packages/board-server/public/third_party/icons/add-circle.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/add-drawable.svg b/packages/board-server/public/third_party/icons/add-drawable.svg deleted file mode 100644 index 754f91d239b..00000000000 --- a/packages/board-server/public/third_party/icons/add-drawable.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/add-file.svg b/packages/board-server/public/third_party/icons/add-file.svg deleted file mode 100644 index 070d5675126..00000000000 --- a/packages/board-server/public/third_party/icons/add-file.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/add-image-webcam.svg b/packages/board-server/public/third_party/icons/add-image-webcam.svg deleted file mode 100644 index 83e3bec1b25..00000000000 --- a/packages/board-server/public/third_party/icons/add-image-webcam.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/add-image.svg b/packages/board-server/public/third_party/icons/add-image.svg deleted file mode 100644 index 81105191c68..00000000000 --- a/packages/board-server/public/third_party/icons/add-image.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/add-inverted.svg b/packages/board-server/public/third_party/icons/add-inverted.svg deleted file mode 100644 index 2fa655a5169..00000000000 --- a/packages/board-server/public/third_party/icons/add-inverted.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/add-text.svg b/packages/board-server/public/third_party/icons/add-text.svg deleted file mode 100644 index f53cf57bcf1..00000000000 --- a/packages/board-server/public/third_party/icons/add-text.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/add-video.svg b/packages/board-server/public/third_party/icons/add-video.svg deleted file mode 100644 index 5ba7aecfbc9..00000000000 --- a/packages/board-server/public/third_party/icons/add-video.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/add.svg b/packages/board-server/public/third_party/icons/add.svg deleted file mode 100644 index db1ca14c3a2..00000000000 --- a/packages/board-server/public/third_party/icons/add.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/arrow-down-48px.svg b/packages/board-server/public/third_party/icons/arrow-down-48px.svg deleted file mode 100644 index 22b4b58ae11..00000000000 --- a/packages/board-server/public/third_party/icons/arrow-down-48px.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/arrow-drop-down.svg b/packages/board-server/public/third_party/icons/arrow-drop-down.svg deleted file mode 100644 index 0e49da6f9ae..00000000000 --- a/packages/board-server/public/third_party/icons/arrow-drop-down.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/arrow-right.svg b/packages/board-server/public/third_party/icons/arrow-right.svg deleted file mode 100644 index ca162180e7d..00000000000 --- a/packages/board-server/public/third_party/icons/arrow-right.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/before.svg b/packages/board-server/public/third_party/icons/before.svg deleted file mode 100644 index 7359ac18b05..00000000000 --- a/packages/board-server/public/third_party/icons/before.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/bug.svg b/packages/board-server/public/third_party/icons/bug.svg deleted file mode 100644 index 9708035eebe..00000000000 --- a/packages/board-server/public/third_party/icons/bug.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/close.svg b/packages/board-server/public/third_party/icons/close.svg deleted file mode 100644 index daa94e80215..00000000000 --- a/packages/board-server/public/third_party/icons/close.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/collapse.svg b/packages/board-server/public/third_party/icons/collapse.svg deleted file mode 100644 index 323685f6ae1..00000000000 --- a/packages/board-server/public/third_party/icons/collapse.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/copy-to-clipboard.svg b/packages/board-server/public/third_party/icons/copy-to-clipboard.svg deleted file mode 100644 index 34727698932..00000000000 --- a/packages/board-server/public/third_party/icons/copy-to-clipboard.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/delete.svg b/packages/board-server/public/third_party/icons/delete.svg deleted file mode 100644 index 8b4bac8789a..00000000000 --- a/packages/board-server/public/third_party/icons/delete.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/download.svg b/packages/board-server/public/third_party/icons/download.svg deleted file mode 100644 index ad9725cd072..00000000000 --- a/packages/board-server/public/third_party/icons/download.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/draft.svg b/packages/board-server/public/third_party/icons/draft.svg deleted file mode 100644 index 73dc9ac5140..00000000000 --- a/packages/board-server/public/third_party/icons/draft.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/edge-connector.svg b/packages/board-server/public/third_party/icons/edge-connector.svg deleted file mode 100644 index 39d59649ee1..00000000000 --- a/packages/board-server/public/third_party/icons/edge-connector.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/edit.svg b/packages/board-server/public/third_party/icons/edit.svg deleted file mode 100644 index 15f5069a764..00000000000 --- a/packages/board-server/public/third_party/icons/edit.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/eject.svg b/packages/board-server/public/third_party/icons/eject.svg deleted file mode 100644 index 2bdf43e4bee..00000000000 --- a/packages/board-server/public/third_party/icons/eject.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/error.svg b/packages/board-server/public/third_party/icons/error.svg deleted file mode 100644 index c8e71add204..00000000000 --- a/packages/board-server/public/third_party/icons/error.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/expand-all-48px.svg b/packages/board-server/public/third_party/icons/expand-all-48px.svg deleted file mode 100644 index 17bb44cf7ae..00000000000 --- a/packages/board-server/public/third_party/icons/expand-all-48px.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/expand.svg b/packages/board-server/public/third_party/icons/expand.svg deleted file mode 100644 index cde1b457211..00000000000 --- a/packages/board-server/public/third_party/icons/expand.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/experiment.svg b/packages/board-server/public/third_party/icons/experiment.svg deleted file mode 100644 index 8768655cce5..00000000000 --- a/packages/board-server/public/third_party/icons/experiment.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/file-add.svg b/packages/board-server/public/third_party/icons/file-add.svg deleted file mode 100644 index 45ae50069fc..00000000000 --- a/packages/board-server/public/third_party/icons/file-add.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/fit.svg b/packages/board-server/public/third_party/icons/fit.svg deleted file mode 100644 index 47b8e6c400f..00000000000 --- a/packages/board-server/public/third_party/icons/fit.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/folder-managed.svg b/packages/board-server/public/third_party/icons/folder-managed.svg deleted file mode 100644 index 8e0cbf5388c..00000000000 --- a/packages/board-server/public/third_party/icons/folder-managed.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/generic-node.svg b/packages/board-server/public/third_party/icons/generic-node.svg deleted file mode 100644 index 6ddbf2d59fc..00000000000 --- a/packages/board-server/public/third_party/icons/generic-node.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/google-drive-48px.svg b/packages/board-server/public/third_party/icons/google-drive-48px.svg deleted file mode 100644 index 7f752af2d76..00000000000 --- a/packages/board-server/public/third_party/icons/google-drive-48px.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/packages/board-server/public/third_party/icons/help.svg b/packages/board-server/public/third_party/icons/help.svg deleted file mode 100644 index a1e40a9f487..00000000000 --- a/packages/board-server/public/third_party/icons/help.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/human-48px.svg b/packages/board-server/public/third_party/icons/human-48px.svg deleted file mode 100644 index fbd5d317729..00000000000 --- a/packages/board-server/public/third_party/icons/human-48px.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/human.svg b/packages/board-server/public/third_party/icons/human.svg deleted file mode 100644 index 6deeb17a527..00000000000 --- a/packages/board-server/public/third_party/icons/human.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/info.svg b/packages/board-server/public/third_party/icons/info.svg deleted file mode 100644 index 715245342fe..00000000000 --- a/packages/board-server/public/third_party/icons/info.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/input.svg b/packages/board-server/public/third_party/icons/input.svg deleted file mode 100644 index 48f3c90bd26..00000000000 --- a/packages/board-server/public/third_party/icons/input.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/javascript.svg b/packages/board-server/public/third_party/icons/javascript.svg deleted file mode 100644 index d1cacb1b9c2..00000000000 --- a/packages/board-server/public/third_party/icons/javascript.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/lan.svg b/packages/board-server/public/third_party/icons/lan.svg deleted file mode 100644 index d287e8b75d5..00000000000 --- a/packages/board-server/public/third_party/icons/lan.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/board-server/public/third_party/icons/laps-48px.svg b/packages/board-server/public/third_party/icons/laps-48px.svg deleted file mode 100644 index b71ff9f4d36..00000000000 --- a/packages/board-server/public/third_party/icons/laps-48px.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/laps.svg b/packages/board-server/public/third_party/icons/laps.svg deleted file mode 100644 index 5c4e48e4d05..00000000000 --- a/packages/board-server/public/third_party/icons/laps.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/lightbulb.svg b/packages/board-server/public/third_party/icons/lightbulb.svg deleted file mode 100644 index d2657de74fb..00000000000 --- a/packages/board-server/public/third_party/icons/lightbulb.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/list.svg b/packages/board-server/public/third_party/icons/list.svg deleted file mode 100644 index 81fb2cf4ee3..00000000000 --- a/packages/board-server/public/third_party/icons/list.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/maximize.svg b/packages/board-server/public/third_party/icons/maximize.svg deleted file mode 100644 index bbebd772a54..00000000000 --- a/packages/board-server/public/third_party/icons/maximize.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/menu.svg b/packages/board-server/public/third_party/icons/menu.svg deleted file mode 100644 index 8cb7aa98d59..00000000000 --- a/packages/board-server/public/third_party/icons/menu.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/merge-type-48px.svg b/packages/board-server/public/third_party/icons/merge-type-48px.svg deleted file mode 100644 index 5ff61dcb265..00000000000 --- a/packages/board-server/public/third_party/icons/merge-type-48px.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/merge-type.svg b/packages/board-server/public/third_party/icons/merge-type.svg deleted file mode 100644 index 190c2f730d5..00000000000 --- a/packages/board-server/public/third_party/icons/merge-type.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/mic-green.svg b/packages/board-server/public/third_party/icons/mic-green.svg deleted file mode 100644 index c3ec3fa38f7..00000000000 --- a/packages/board-server/public/third_party/icons/mic-green.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/minimize.svg b/packages/board-server/public/third_party/icons/minimize.svg deleted file mode 100644 index 770d54a59db..00000000000 --- a/packages/board-server/public/third_party/icons/minimize.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/model.svg b/packages/board-server/public/third_party/icons/model.svg deleted file mode 100644 index 61f5c549aa1..00000000000 --- a/packages/board-server/public/third_party/icons/model.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/more-vert-inverted.svg b/packages/board-server/public/third_party/icons/more-vert-inverted.svg deleted file mode 100644 index af6b06d0246..00000000000 --- a/packages/board-server/public/third_party/icons/more-vert-inverted.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/move-down.svg b/packages/board-server/public/third_party/icons/move-down.svg deleted file mode 100644 index c66e3107231..00000000000 --- a/packages/board-server/public/third_party/icons/move-down.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/move-up.svg b/packages/board-server/public/third_party/icons/move-up.svg deleted file mode 100644 index d952b3d91a4..00000000000 --- a/packages/board-server/public/third_party/icons/move-up.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/nano-48px.svg b/packages/board-server/public/third_party/icons/nano-48px.svg deleted file mode 100644 index 3516604da0a..00000000000 --- a/packages/board-server/public/third_party/icons/nano-48px.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/board-server/public/third_party/icons/next.svg b/packages/board-server/public/third_party/icons/next.svg deleted file mode 100644 index 21702f7cdb3..00000000000 --- a/packages/board-server/public/third_party/icons/next.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/open-new.svg b/packages/board-server/public/third_party/icons/open-new.svg deleted file mode 100644 index d96e3b86e13..00000000000 --- a/packages/board-server/public/third_party/icons/open-new.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/password.svg b/packages/board-server/public/third_party/icons/password.svg deleted file mode 100644 index 8b7928cec6e..00000000000 --- a/packages/board-server/public/third_party/icons/password.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/public.svg b/packages/board-server/public/third_party/icons/public.svg deleted file mode 100644 index 6ab0c02e207..00000000000 --- a/packages/board-server/public/third_party/icons/public.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/quick-jump.svg b/packages/board-server/public/third_party/icons/quick-jump.svg deleted file mode 100644 index 7a63e4cb304..00000000000 --- a/packages/board-server/public/third_party/icons/quick-jump.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/recent.svg b/packages/board-server/public/third_party/icons/recent.svg deleted file mode 100644 index bf5cc1bd944..00000000000 --- a/packages/board-server/public/third_party/icons/recent.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/refresh.svg b/packages/board-server/public/third_party/icons/refresh.svg deleted file mode 100644 index 25eb0f2d45e..00000000000 --- a/packages/board-server/public/third_party/icons/refresh.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/reset-image.svg b/packages/board-server/public/third_party/icons/reset-image.svg deleted file mode 100644 index 6e791c016b4..00000000000 --- a/packages/board-server/public/third_party/icons/reset-image.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/reset-nodes.svg b/packages/board-server/public/third_party/icons/reset-nodes.svg deleted file mode 100644 index 864b75dc052..00000000000 --- a/packages/board-server/public/third_party/icons/reset-nodes.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/rsvp.svg b/packages/board-server/public/third_party/icons/rsvp.svg deleted file mode 100644 index 0c232c26787..00000000000 --- a/packages/board-server/public/third_party/icons/rsvp.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/save-as.svg b/packages/board-server/public/third_party/icons/save-as.svg deleted file mode 100644 index 080826a3a58..00000000000 --- a/packages/board-server/public/third_party/icons/save-as.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/save-inverted.svg b/packages/board-server/public/third_party/icons/save-inverted.svg deleted file mode 100644 index 99793c4e4dd..00000000000 --- a/packages/board-server/public/third_party/icons/save-inverted.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/save.svg b/packages/board-server/public/third_party/icons/save.svg deleted file mode 100644 index b0ea7f89c7b..00000000000 --- a/packages/board-server/public/third_party/icons/save.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/search.svg b/packages/board-server/public/third_party/icons/search.svg deleted file mode 100644 index 74e3e249e90..00000000000 --- a/packages/board-server/public/third_party/icons/search.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/settings-inverted.svg b/packages/board-server/public/third_party/icons/settings-inverted.svg deleted file mode 100644 index d6807ece261..00000000000 --- a/packages/board-server/public/third_party/icons/settings-inverted.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/settings.svg b/packages/board-server/public/third_party/icons/settings.svg deleted file mode 100644 index 351422d5b7d..00000000000 --- a/packages/board-server/public/third_party/icons/settings.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/smart-toy-48px.svg b/packages/board-server/public/third_party/icons/smart-toy-48px.svg deleted file mode 100644 index dbee75150c9..00000000000 --- a/packages/board-server/public/third_party/icons/smart-toy-48px.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/smart-toy.svg b/packages/board-server/public/third_party/icons/smart-toy.svg deleted file mode 100644 index ccb49abcab2..00000000000 --- a/packages/board-server/public/third_party/icons/smart-toy.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/sound.svg b/packages/board-server/public/third_party/icons/sound.svg deleted file mode 100644 index fa7563208e8..00000000000 --- a/packages/board-server/public/third_party/icons/sound.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/stop-circle.svg b/packages/board-server/public/third_party/icons/stop-circle.svg deleted file mode 100644 index 3482437a308..00000000000 --- a/packages/board-server/public/third_party/icons/stop-circle.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/toggle-off.svg b/packages/board-server/public/third_party/icons/toggle-off.svg deleted file mode 100644 index 0e6be1fddcb..00000000000 --- a/packages/board-server/public/third_party/icons/toggle-off.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/toggle-on.svg b/packages/board-server/public/third_party/icons/toggle-on.svg deleted file mode 100644 index 3556c6a5c0e..00000000000 --- a/packages/board-server/public/third_party/icons/toggle-on.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/tool.svg b/packages/board-server/public/third_party/icons/tool.svg deleted file mode 100644 index 58974845be2..00000000000 --- a/packages/board-server/public/third_party/icons/tool.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/undo-inverted.svg b/packages/board-server/public/third_party/icons/undo-inverted.svg deleted file mode 100644 index c84baedaa3f..00000000000 --- a/packages/board-server/public/third_party/icons/undo-inverted.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/unfold-less.svg b/packages/board-server/public/third_party/icons/unfold-less.svg deleted file mode 100644 index 70114f4b4d9..00000000000 --- a/packages/board-server/public/third_party/icons/unfold-less.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/unfold-more.svg b/packages/board-server/public/third_party/icons/unfold-more.svg deleted file mode 100644 index 097a7e10ed9..00000000000 --- a/packages/board-server/public/third_party/icons/unfold-more.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/verified.svg b/packages/board-server/public/third_party/icons/verified.svg deleted file mode 100644 index 888f2cf7c21..00000000000 --- a/packages/board-server/public/third_party/icons/verified.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/visibility-off.svg b/packages/board-server/public/third_party/icons/visibility-off.svg deleted file mode 100644 index 15737646f00..00000000000 --- a/packages/board-server/public/third_party/icons/visibility-off.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/public/third_party/icons/warning.svg b/packages/board-server/public/third_party/icons/warning.svg deleted file mode 100644 index bebda1b2725..00000000000 --- a/packages/board-server/public/third_party/icons/warning.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/packages/board-server/scripts/build.ts b/packages/board-server/scripts/build.ts deleted file mode 100644 index 9603fb20b1b..00000000000 --- a/packages/board-server/scripts/build.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as esbuild from "esbuild"; - -await Promise.all([ - esbuild.build({ - entryPoints: ["src/index.ts"], - bundle: true, - platform: "node", - external: ["@google-cloud", "import.meta", "vite", "better-sqlite3"], - format: "esm", - outfile: "dist/server/index.js", - sourcemap: true - }), - esbuild.build({ - entryPoints: ["scripts/create-account.ts"], - bundle: true, - platform: "node", - format: "esm", - outfile: "dist/scripts/create-account.js", - sourcemap: true, - external: ["@google-cloud", "import.meta", "vite", "better-sqlite3"], - }) -]); diff --git a/packages/board-server/scripts/create-account.ts b/packages/board-server/scripts/create-account.ts deleted file mode 100644 index b99c7b67fb9..00000000000 --- a/packages/board-server/scripts/create-account.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createAccount } from "../src/server/store.js" - -if (process.argv.length !== 3) { - console.error("Usage: create-account "); - process.exit(1); -} - - -const username = process.argv[2]; - -const {api_key} = await createAccount(username!) - -console.log(`Created account for ${username} with API key:\n${api_key}`); diff --git a/packages/board-server/scripts/make-og-image.html b/packages/board-server/scripts/make-og-image.html deleted file mode 100644 index 81ea538df15..00000000000 --- a/packages/board-server/scripts/make-og-image.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - Board Server OG Image Generator - - -

Save the image as ./public/images/og-image.png

- - - - - diff --git a/packages/board-server/src/api-view/api-view.ts b/packages/board-server/src/api-view/api-view.ts deleted file mode 100644 index acc79635b70..00000000000 --- a/packages/board-server/src/api-view/api-view.ts +++ /dev/null @@ -1,621 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { customElement, property, state } from "lit/decorators.js"; -import { LitElement, css, html, nothing, type PropertyValueMap } from "lit"; - -import Core from "@google-labs/core-kit"; -import JSONKit from "@google-labs/json-kit"; -import TemplateKit from "@google-labs/template-kit"; -import NodeNurseryWeb from "@google-labs/node-nursery-web"; -import PaLMKit from "@google-labs/palm-kit"; -import GeminiKit from "@google-labs/gemini-kit"; -import AgentKit from "@google-labs/agent-kit"; - -import { loadKits } from "./utils/kit-loader.js"; -import { - createLoader, - createRunObserver, - type GraphProvider, - type InputValues, - type InspectableRun, - type InspectableRunObserver, - type Kit, - type Schema, -} from "@google-labs/breadboard"; -import { - run, - type HarnessRunResult, - type RunConfig, -} from "@google-labs/breadboard/harness"; -import type { InputResolveRequest } from "@google-labs/breadboard/remote"; -import { until } from "lit/directives/until.js"; -import { isBoolean, isMultiline, isSelect } from "./utils/input.js"; -import { createRef, ref, type Ref } from "lit/directives/ref.js"; - -import { getDataStore, getRunStore } from "@breadboard-ai/data-store"; - -type inputCallback = (data: Record) => void; - -enum STATUS { - RUNNING, - STOPPED, - LOADING, -} - -@customElement("bb-api-explorer") -export class ApiExplorer extends LitElement { - @property() - url: string | null = null; - - @property() - run: string | null = null; - - @state() - runs: InspectableRun[] | null = null; - - @state() - status = STATUS.STOPPED; - - @state() - dataStore = getDataStore(); - - @state() - runStore = getRunStore(); - - #kits: Kit[] = []; - #runObserver: InspectableRunObserver = createRunObserver({ - dataStore: this.dataStore, - runStore: this.runStore, - }); - #handlers: Map = new Map(); - #providers: GraphProvider[] = []; - #kitLoad = loadKits([ - TemplateKit, - Core, - PaLMKit, - GeminiKit, - NodeNurseryWeb, - JSONKit, - AgentKit, - ]); - - #loader = createLoader(this.#providers); - #load: Promise<{ - title: string | undefined; - description: string | undefined; - }> | null = null; - #contentRef: Ref = createRef(); - #outputs = new Map(); - #secrets: Record = {}; - - static override styles = css` - * { - box-sizing: border-box; - } - - :host { - margin: 0; - padding: 0; - height: 100%; - width: 100%; - color: var(--bb-neutral-0); - } - - main { - display: grid; - grid-template-rows: 52px auto; - height: 100%; - width: 100%; - overflow: auto; - } - - header { - background: var(--bb-neutral-900); - padding: var(--bb-grid-size-3) var(--bb-grid-size-4); - } - - header h1 { - margin: 0; - padding-bottom: var(--bb-grid-size-3); - font: 400 var(--bb-title-large) / var(--bb-title-line-height-large) - var(--bb-font-family); - display: flex; - align-items: center; - } - - section { - position: relative; - overflow: auto; - width: 100%; - scrollbar-gutter: stable; - } - - #content { - max-width: 800px; - margin: 0 auto; - font: 400 var(--bb-body-medium) / var(--bb-body-line-height-medium) - var(--bb-font-family); - padding: 0 var(--bb-grid-size-4) var(--bb-grid-size-12) - var(--bb-grid-size-4); - } - - #content table { - width: 100%; - margin-top: var(--bb-grid-size-6); - } - - #content thead td { - font-weight: bold; - } - - #content td { - vertical-align: middle; - } - - #content td.parameter { - width: 10%; - } - - #content td.value { - width: 65%; - } - - #content td.description { - width: 20%; - } - - #content td.type { - width: 5%; - } - - #content textarea, - #content input[type="text"], - #content input[type="password"], - #content select { - background: var(--bb-neutral-800); - font: normal var(--bb-body-medium) / var(--bb-body-line-height-medium) - var(--bb-font-family); - color: var(--bb-neutral-0); - white-space: pre-line; - resize: none; - padding: var(--bb-grid-size); - border: 1px solid var(--bb-neutral-600); - border-radius: var(--bb-grid-size-2); - width: 100%; - outline: none; - max-height: 200px; - white-space: pre-line; - scrollbar-width: none; - margin-top: 6px; - } - - #content textarea, - #content input[type="text"] { - field-sizing: content; - } - - #content input[type="submit"] { - background: var(--bb-neutral-900); - border: none; - border-radius: var(--bb-grid-size-10); - color: var(--bb-neutral-0); - padding: var(--bb-grid-size) var(--bb-grid-size-3); - font: normal var(--bb-label-small) / var(--bb-label-line-height-small) - var(--bb-font-family); - } - - #content img { - border-radius: var(--bb-grid-size-3); - width: 100%; - } - `; - - override connectedCallback(): void { - super.connectedCallback(); - - const currentUrl = new URL(window.location.href); - const newPathname = currentUrl.pathname.replace(/\.api$/, ".json"); - currentUrl.pathname = newPathname; - this.url = currentUrl.href; - } - - protected willUpdate( - changedProperties: - | PropertyValueMap<{ url: string }> - | Map - ): void { - if (!changedProperties.has("url")) { - return; - } - - if (!this.url) { - return; - } - - this.#load = this.#kitLoad.then(async (kits) => { - this.#kits = kits; - if (!this.url) { - return { title: "Error", description: "No URL" }; - } - - try { - const response = await fetch(this.url); - await response.json(); - } catch (err) { - return { title: "Error", description: "Unable to load file" }; - } - - const board = await this.#getBoardInfo(this.url); - this.#runBoard(this.url); - - return board; - }); - } - - #restored = false; - async restoreProvidersAndSettingsIfNeeded() { - if (this.#restored) { - return; - } - - this.#restored = true; - const jobs = this.#providers.map((provider) => provider.restore()); - await Promise.all(jobs); - } - - async #getBoardInfo(url: string) { - const loader = createLoader([]); - const base = new URL(window.location.href); - const graph = await loader.load(url, { base }); - if (!graph) { - // TODO: Better error handling, maybe a toast? - throw new Error(`Unable to load graph: ${url}`); - } - const runner = graph; - const { title, description } = runner; - - if (title) { - window.document.title = title; - } - - return { title, description }; - } - - async #runBoard(url: string | null) { - if (!url) { - return; - } - - await this.restoreProvidersAndSettingsIfNeeded(); - - const config: RunConfig = { - url, - kits: this.#kits, - diagnostics: true, - loader: this.#loader, - store: this.dataStore, - interactiveSecrets: true, - inputs: { - model: "gemini-1.5-flash-latest", - }, - }; - - this.status = STATUS.RUNNING; - this.#outputs.clear(); - for await (const result of run(config)) { - await this.#runObserver?.observe(result); - this.requestUpdate(); - - const answer = await this.#handleStateChange(result); - - if (answer) { - await result.reply({ inputs: answer } as InputResolveRequest); - } - } - this.status = STATUS.STOPPED; - } - - async #registerInputHandler(id: string): Promise { - const handlers = this.#handlers.get(id); - if (!handlers) { - return Promise.reject(`Unable to set up handler for input ${id}`); - } - - return new Promise((resolve) => { - handlers.push((data: Record) => { - resolve(data as InputValues); - }); - }); - } - - async #registerSecretsHandler(keys: string[]): Promise { - const values = await Promise.all( - keys.map((key) => { - if (this.#secrets && this.#secrets[key]) { - return Promise.resolve([key, this.#secrets[key]]); - } - - return new Promise<[string, unknown]>((resolve) => { - const callback = ({ secret }: Record) => { - this.#secrets = this.#secrets || {}; - this.#secrets[key] = secret as string; - - resolve([key, secret]); - }; - this.#handlers.set(key, [callback]); - }); - }) - ); - - return Object.fromEntries(values) as InputValues; - } - - async #handleStateChange( - result: HarnessRunResult - ): Promise { - this.requestUpdate(); - - const { data, type } = result; - switch (type) { - case "nodestart": { - if (!this.#handlers.has(data.node.id)) { - this.#handlers.set(data.node.id, []); - } - return; - } - - case "nodeend": { - this.#handlers.delete(data.node.id); - return; - } - - case "input": { - return this.#registerInputHandler(data.node.id); - } - - case "secret": { - return this.#registerSecretsHandler(data.keys); - } - } - } - - #createInput(properties: Record) { - return html`${Object.entries(properties).map(([key, property]) => { - let input; - if (isSelect(property)) { - // Select input. - const options = property.enum || []; - input = html` `; - } else if (isBoolean(property)) { - // Checkbox / Boolean input. - const checked = property.default ?? false; - input = html``; - } else { - // Text inputs: multi line and single line. - const examples = property.examples?.[0]; - let value = examples ?? property.default ?? ""; - value = - typeof value === "string" ? value : JSON.stringify(value, null, 2); - if (isMultiline(property)) { - // Multi line input. - input = html` - - `; - } else { - // Single line input. - input = html``; - } - } - - return html` - ${key ?? "(no id)"} - - ${input} - - ${property.description ?? "(no description)"} - ${property.type} - `; - })}`; - } - - override render() { - if (!this.url) { - return html`Unable to load - is this board URL correct?`; - } - - if (!this.#load) { - return nothing; - } - - const handleForm = (evt: SubmitEvent) => { - evt.preventDefault(); - - if (!(evt.target instanceof HTMLFormElement)) { - return; - } - - const formData = new FormData(evt.target); - const handlerId = formData.get("id") as string; - if (!handlerId) { - console.warn("Form received with no ID"); - return; - } - - let data: Record = {}; - if (formData.has("initial-input")) { - const initialInputValue = formData.get("initial-input-value") as string; - data = { - text: { - role: "user", - parts: [ - { - text: initialInputValue, - }, - ], - }, - }; - } else if (formData.has("secret")) { - const secret = formData.get("secret"); - data = { secret }; - } else { - formData.forEach((value, key) => { - if (key.endsWith("-data-type")) { - return; - } - - const typeInfo = formData.get(`${key}-data-type`); - if (typeInfo && typeInfo === "object" && typeof value === "string") { - try { - value = JSON.parse(value); - } catch (err) { - console.warn(err); - return; - } - } - - data[key] = value; - }); - } - - const handlers = this.#handlers.get(handlerId) || []; - if (handlers.length === 0) { - console.warn( - `Received event for input(id="${handlerId}") but no handlers were found` - ); - } - - for (const handler of handlers) { - handler.call(null, data); - } - }; - - const loadData = this.#load.then(async ({ title, description }) => { - if (title === "Error") { - return html`${description}`; - } - - const currentRun = (await this.#runObserver.runs())[0]; - const events = currentRun?.events || []; - const eventPosition = events.length - 1; - const topEvent = events[eventPosition]; - - let content; - if (topEvent?.type === "secret") { - content = html`
- - - - - - - - - - - - - - - - - - -
ParameterValueDescriptionType
${topEvent.keys.join(", ")} - - (no description)string
- -
`; - } - - if (topEvent?.type === "node" && !topEvent.hidden) { - const nodeType = topEvent.node.descriptor.type; - if (nodeType === "input") { - const configuration = topEvent.inputs; - const schema = configuration.schema as Schema; - if (schema) { - const properties = schema.properties as Record; - content = html`
- - - - - - - - - - - - ${this.#createInput(properties)} - -
ParameterValueDescriptionType
- -
`; - } else { - content = html`No schema`; - } - } else { - content = html`Error: unexpected node`; - } - } - - if (topEvent?.type === "error") { - content = html`Error: ${JSON.stringify(topEvent.error, null, 2)}`; - } - - return html`
-
-

${title || "Untitled board"} - API Explorer

-
-
-
${content}
-
-
`; - }); - - return html`${until(loadData)}`; - } -} diff --git a/packages/board-server/src/api-view/types.ts b/packages/board-server/src/api-view/types.ts deleted file mode 100644 index b0374709850..00000000000 --- a/packages/board-server/src/api-view/types.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export type LLMInlineData = { - inlineData: { data: string; mimeType: string }; -}; - -export type LLMFunctionCall = { - functionCall: { - name: string; - args: object; - }; -}; - -export type LLMFunctionResponse = { - functionResponse: { - name: string; - response: object; - }; -}; - -export type LLMText = { - text: string; -}; - -export type LLMStoredData = { - storedData: { - handle: string; - mimeType: string; - }; -}; - -export type LLMPart = - | LLMInlineData - | LLMStoredData - | LLMFunctionCall - | LLMFunctionResponse - | LLMText; - -export type LLMContent = { - role?: string; - parts: LLMPart[]; -}; diff --git a/packages/board-server/src/api-view/utils/input.ts b/packages/board-server/src/api-view/utils/input.ts deleted file mode 100644 index 952ca115566..00000000000 --- a/packages/board-server/src/api-view/utils/input.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { Schema } from "@google-labs/breadboard"; - -export function isMultiline(schema: Schema) { - return ( - schema.format === "multiline" || - schema.type === "object" || - schema.type === "array" - ); -} - -export function isSelect(schema: Schema) { - return schema.enum && schema.enum.length > 0; -} - -export function isBoolean(schema: Schema) { - return schema.type == "boolean"; -} diff --git a/packages/board-server/src/api-view/utils/kit-loader.ts b/packages/board-server/src/api-view/utils/kit-loader.ts deleted file mode 100644 index 94144f4eb84..00000000000 --- a/packages/board-server/src/api-view/utils/kit-loader.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - type KitConstructor, - type Kit, - asRuntimeKit, -} from "@google-labs/breadboard"; - -export const loadKits = async (kiConstructors: KitConstructor[]) => { - return kiConstructors.map((kitConstructor) => asRuntimeKit(kitConstructor)); -}; diff --git a/packages/board-server/src/api-view/utils/output.ts b/packages/board-server/src/api-view/utils/output.ts deleted file mode 100644 index 2b3bd243d65..00000000000 --- a/packages/board-server/src/api-view/utils/output.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - LLMFunctionCall, - LLMFunctionResponse, - LLMInlineData, - LLMPart, - LLMStoredData, - LLMText, -} from "../types.js"; - -export function isText(part: LLMPart): part is LLMText { - return "text" in part; -} - -export function isFunctionCall(part: LLMPart): part is LLMFunctionCall { - return "functionCall" in part; -} - -export function isFunctionResponse(part: LLMPart): part is LLMFunctionResponse { - return "functionResponse" in part; -} - -export function isInlineData(part: LLMPart): part is LLMInlineData { - return "inlineData" in part; -} - -export function isStoredData(part: LLMPart): part is LLMStoredData { - return "storedData" in part; -} diff --git a/packages/board-server/src/api-view/utils/vite-env.d.ts b/packages/board-server/src/api-view/utils/vite-env.d.ts deleted file mode 100644 index 11f02fe2a00..00000000000 --- a/packages/board-server/src/api-view/utils/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/packages/board-server/src/app/app.ts b/packages/board-server/src/app/app.ts deleted file mode 100644 index aacb66d6a9f..00000000000 --- a/packages/board-server/src/app/app.ts +++ /dev/null @@ -1,1030 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { LitElement, html, css, type PropertyValueMap, nothing } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import { classMap } from "lit/directives/class-map.js"; -import { - BoardServerAPIKeyEnterEvent, - InputEnterEvent, - RunContextChangeEvent, - SecretsEnterEvent, - ToastEvent, -} from "./events/events.js"; -import { - createDefaultDataStore, - createLoader, - type GraphDescriptor, - type InputValues, -} from "@google-labs/breadboard"; -import { - createRunner, - type HarnessRunner, - type RunConfig, -} from "@google-labs/breadboard/harness"; -import { STATUS, type UserMessage } from "./types/types.js"; -import { until } from "lit/directives/until.js"; -import { loadKits } from "./utils/kit-loader.js"; - -import Core from "@google-labs/core-kit"; -import JSONKit from "@google-labs/json-kit"; -import TemplateKit from "@google-labs/template-kit"; -import GeminiKit from "@google-labs/gemini-kit"; -import AgentKit from "@google-labs/agent-kit"; - -import * as BreadboardUI from "@breadboard-ai/shared-ui"; -import "./elements/elements.js"; -import { - VisitorStateManager, - visitorStateManagerContext, -} from "./utils/visitor-state-manager.js"; -import { map } from "lit/directives/map.js"; -import { provide } from "@lit/context"; -import { VisitorState } from "./utils/types.js"; -import { AppSettingsHelper } from "./utils/settings-helper.js"; - -const RUN_ON_BOARD_SERVER = "run-on-board-server"; - -const ENVIRONMENT: BreadboardUI.Contexts.Environment = { - connectionServerUrl: import.meta.env.VITE_CONNECTION_SERVER_URL, - connectionRedirectUrl: "/oauth/", - plugins: { - input: [ - BreadboardUI.Elements.googleDriveFileIdInputPlugin, - BreadboardUI.Elements.googleDriveQueryInputPlugin, - ], - }, -}; - -const randomMessage: UserMessage[] = [ - { - srcset: "https://fonts.gstatic.com/s/e/notoemoji/latest/1f648/512.webp", - src: "https://fonts.gstatic.com/s/e/notoemoji/latest/1f648/512.gif", - alt: "🙈", - }, - { - srcset: - "https://fonts.gstatic.com/s/e/notoemoji/latest/1f636_200d_1f32b_fe0f/512.webp", - src: "https://fonts.gstatic.com/s/e/notoemoji/latest/1f636_200d_1f32b_fe0f/512.gif", - alt: "😶", - }, - { - srcset: "https://fonts.gstatic.com/s/e/notoemoji/latest/1f9d0/512.webp", - src: "https://fonts.gstatic.com/s/e/notoemoji/latest/1f9d0/512.gif", - alt: "🧐", - }, - { - srcset: "https://fonts.gstatic.com/s/e/notoemoji/latest/1f4a1/512.webp", - src: "https://fonts.gstatic.com/s/e/notoemoji/latest/1f4a1/512.gif", - alt: "💡", - }, -]; - -const getRemoteURL = () => { - const url = new URL(window.location.href); - url.pathname = url.pathname.replace(/app$/, "api/run"); - return url.href; -}; - -@customElement("bb-app-view") -export class AppView extends LitElement { - @property({ reflect: true }) - url: string | null = null; - - @property({ reflect: true }) - version: string = "dev"; - - @state() - status = STATUS.STOPPED; - - @state() - showMenu = false; - - @state() - showServerKeyPopover = false; - - @state() - showInvitesPopover = false; - - @state() - statusMessage: string | null = null; - - @state() - runOnBoardServer = false; - - @state() - boardKeyNeeded = false; - - @state() - canInviteOthers = false; - - @state() - visitorState: VisitorState = VisitorState.LOADING; - - @state() - secretsNeeded: string[] | null = null; - - @provide({ context: BreadboardUI.Contexts.environmentContext }) - environment = ENVIRONMENT; - - @provide({ context: BreadboardUI.Elements.tokenVendorContext }) - tokenVendor!: BreadboardUI.Elements.TokenVendor; - - @provide({ context: BreadboardUI.Contexts.settingsHelperContext }) - settingsHelper!: AppSettingsHelper; - - @provide({ context: visitorStateManagerContext }) - visitorStateManager = new VisitorStateManager(); - - #toasts = new Map< - string, - { - message: string; - type: BreadboardUI.Events.ToastType; - persistent: boolean; - } - >(); - - #statusMessageTime: string | null = null; - #loader = createLoader([]); - #dataStore = createDefaultDataStore(); - #descriptorLoad: Promise = Promise.resolve(null); - #kitLoad = loadKits([TemplateKit, Core, GeminiKit, JSONKit, AgentKit]); - #visitorStateInit = Promise.resolve(); - - #isSharing = false; - #abortController: AbortController | null = null; - #runObserver: BreadboardUI.Utils.TopGraphObserver | null = null; - #runner: HarnessRunner | null = null; - #runStartTime = 0; - #message = randomMessage[Math.floor(Math.random() * randomMessage.length)]!; - #formatter = new Intl.DateTimeFormat(navigator.languages, { - month: "long", - day: "numeric", - hour: "numeric", - minute: "2-digit", - hour12: true, - }); - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: block; - font: var(--bb-font-body-medium); - height: 100%; - } - - bb-toast { - z-index: 200; - } - - main { - display: grid; - grid-template-columns: none; - grid-template-rows: 48px auto; - } - - #loading { - padding: var(--bb-grid-size-4); - display: flex; - align-items: center; - } - - #loading::before { - content: ""; - width: 16px; - height: 16px; - background: transparent url(/images/progress-ui.svg) 0 center / 16px 16px - no-repeat; - margin-right: var(--bb-grid-size); - } - - #board-description, - #help { - display: none; - color: var(--bb-neutral-600); - } - - header { - display: flex; - align-items: center; - } - - #menu-toggle { - width: 20px; - height: 20px; - background: transparent var(--bb-icon-menu-inverted) center center / 20px - 20px no-repeat; - border: none; - font-size: 0; - margin-right: var(--bb-grid-size-2); - } - - h1 { - font: var(--bb-font-title-small); - margin: 0; - } - - p { - margin: 0 0 var(--bb-grid-size-2) 0; - } - - footer { - position: fixed; - bottom: 0; - height: calc(var(--bb-grid-size-13) + var(--bb-grid-size-12)); - display: grid; - grid-template-columns: none; - grid-template-rows: var(--bb-grid-size-13) var(--bb-grid-size-8); - background: var(--bb-neutral-0); - border-top: 1px solid var(--bb-neutral-300); - width: 100%; - font: var(--bb-font-body-small); - align-items: center; - } - - #links { - color: var(--bb-neutral-400); - grid-row: 2/3; - padding: 0 var(--bb-grid-size-2); - } - - #links a { - color: var(--bb-neutral-500); - font-weight: bold; - text-decoration: none; - } - - #controls { - position: relative; - display: flex; - align-items: center; - width: 100%; - justify-content: space-between; - background: var(--bb-neutral-0); - z-index: 1; - } - - #status { - max-width: calc(100vw - 160px); - flex: 1 1 auto; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - padding: 0 var(--bb-grid-size-2); - font: var(--bb-font-title-small); - color: var(--bb-neutral-700); - } - - #status.pending { - padding: 0 var(--bb-grid-size-2) 0 var(--bb-grid-size-8); - background: transparent url(/images/progress-ui.svg) var(--bb-grid-size-2) - center / 16px 16px no-repeat; - } - - #status .messages-received { - color: var(--bb-neutral-500); - margin-left: var(--bb-grid-size-4); - } - - #main-control { - height: 32px; - background: var(--bb-ui-500); - border-radius: 30px; - padding: var(--bb-grid-size) var(--bb-grid-size-5); - border: 1px solid var(--bb-ui-500); - color: var(--bb-neutral-0); - flex: 0 0 auto; - margin: 0 var(--bb-grid-size-2) 0 var(--bb-grid-size-3); - cursor: pointer; - transition: background-color 0.3s cubic-bezier(0, 0, 0.3, 1); - } - - #main-control:hover, - #main-control:focus { - background: var(--bb-ui-600); - transition-duration: 0.15s; - } - - #main-control.active { - background: var(--bb-neutral-0); - border: 1px solid var(--bb-ui-200); - color: var(--bb-ui-600); - } - - #main-control.active:hover, - #main-control.active:focus { - background: var(--bb-ui-50); - transition-duration: 0.15s; - } - - #board-info h1 { - color: var(--bb-neutral-0); - } - - #board-info bb-app-nav { - display: none; - } - - #board-info-container { - display: flex; - align-items: center; - padding: var(--bb-grid-size) var(--bb-grid-size-2); - background: var(--bb-ui-500); - } - - @media (min-width: 700px) { - main { - display: grid; - grid-template-columns: max(300px, 20vw) 1fr; - grid-template-rows: none; - column-gap: var(--bb-grid-size-5); - } - - bb-app-nav[popout] { - display: none; - } - - #board-info { - width: 100%; - } - - #board-info-container { - background: var(--bb-neutral-0); - border-bottom: 1px solid var(--bb-neutral-300); - } - - #board-info h1 { - color: var(--bb-ui-500); - } - - #menu-toggle { - background-image: var(--bb-icon-menu); - } - - footer { - height: var(--bb-grid-size-13); - grid-template-columns: max(300px, 20vw) 1fr; - grid-template-rows: none; - column-gap: var(--bb-grid-size-5); - } - - #links { - grid-row: auto; - padding-left: var(--bb-grid-size-4); - } - - #status { - max-width: calc(100vw - 180px - max(300px, 20vw)); - } - - h1 { - font: var(--bb-font-title-large); - margin: 0; - } - - section { - display: block; - } - - #activity { - position: relative; - } - - #board-info { - position: sticky; - top: 0; - padding: 0; - background: var(--bb-neutral-0); - } - - #board-info bb-app-nav { - display: block; - } - - #board-info #menu-toggle { - display: none; - } - - #board-info-container { - align-items: flex-start; - border-bottom: none; - padding: 0; - } - - #board-description, - #help { - display: block; - margin-top: var(--bb-grid-size-2); - padding: 0 var(--bb-grid-size-4); - } - - #help { - border-top: 1px solid var(--bb-neutral-300); - margin-top: var(--bb-grid-size-8); - padding-top: var(--bb-grid-size-8); - color: var(--bb-neutral-500); - } - - #board-info h1 { - padding: var(--bb-grid-size-5) var(--bb-grid-size-4) 0 - var(--bb-grid-size-4); - } - } - - @media (min-width: 1120px) { - #activity, - #controls { - width: 750px; - left: calc(50% - 250px - (max(300px, 20vw) / 2)); - } - } - `; - - constructor() { - super(); - this.settingsHelper = new AppSettingsHelper(); - this.tokenVendor = new BreadboardUI.Elements.TokenVendor( - this.settingsHelper, - ENVIRONMENT - ); - } - - connectedCallback(): void { - super.connectedCallback(); - - this.url = window.location.pathname.replace(/app$/, "json"); - const runOnBoardServer = - globalThis.localStorage.getItem(RUN_ON_BOARD_SERVER); - this.runOnBoardServer = runOnBoardServer === "true"; - - this.visitorStateManager.addEventListener("change", (evt) => { - this.visitorState = evt.state; - const upgradeToRunOnServer = evt.previous < VisitorState.INVITEE; - const alreadySet = - evt.previous === VisitorState.LOADING && runOnBoardServer !== null; - if (upgradeToRunOnServer && !alreadySet) { - this.#toggleRunContext(new RunContextChangeEvent("remote")); - } - }); - this.#visitorStateInit = this.visitorStateManager.init(); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - - this.stopRun(); - } - - protected willUpdate( - changedProperties: - | PropertyValueMap<{ - url: string | null; - runOnBoardServer: boolean; - boardServerKey: string | null; - }> - | Map - ): void { - if (changedProperties.has("url")) { - this.#descriptorLoad = new Promise(async (resolve) => { - if (!this.url) { - resolve(null); - return; - } - - try { - const response = await fetch(this.url); - const graph = (await response.json()) as GraphDescriptor; - const title = !!graph.title; - document.title = `${title ? `${graph.title} - ` : ""}Breadboard App View`; - resolve(graph); - this.startRun(); - } catch (err) { - console.warn(err); - resolve(null); - } - }); - } - - if ( - changedProperties.has("runOnBoardServer") || - changedProperties.has("boardServerKey") - ) { - if (this.runOnBoardServer) { - this.boardKeyNeeded = - this.visitorStateManager.boardServerKey() === null; - } else { - this.boardKeyNeeded = false; - } - } - } - - stopRun() { - this.status = STATUS.STOPPED; - - this.#abortRun("Stopped"); - this.#runner = null; - } - - #helpText() { - const local = html`

- You will be asked for various API keys. These keys will be stored in your - local browser storage so that you don't have to re-enter them. -

`; - const flip = html`

- Flip the "Run on Server" toggle to run this app without having to enter - keys. -

`; - const invite = html`

- You own the board for this app, so you can invite others to run it on - server. Click "Manage Invites" to create or delete invites. -

`; - const remote = nothing; - switch (this.visitorState) { - case VisitorState.VISITOR: { - return local; - } - case VisitorState.USER: - case VisitorState.INVITEE: { - if (this.runOnBoardServer) { - return remote; - } else { - return html`${local}${flip}`; - } - } - case VisitorState.OWNER: { - if (this.runOnBoardServer) { - return invite; - } else { - return html`${local}${flip}${invite}`; - } - } - default: { - return nothing; - } - } - } - - async startRun() { - this.stopRun(); - - const [graph, kits] = await Promise.all([ - this.#descriptorLoad, - this.#kitLoad, - this.#visitorStateInit, - ]); - - if (!graph || !kits || !this.url) { - return; - } - - this.#abortController = new AbortController(); - - const config: RunConfig = { - url: this.url, - kits, - runner: graph, - loader: this.#loader, - signal: this.#abortController.signal, - diagnostics: "top", - store: this.#dataStore, - interactiveSecrets: true, - inputs: { - model: "gemini-1.5-flash-latest", - }, - }; - - if ( - this.runOnBoardServer && - this.visitorStateManager.visitorState() >= VisitorState.INVITEE - ) { - const boardServerKey = this.visitorStateManager.boardServerKey(); - if (boardServerKey) { - config.remote = { - url: getRemoteURL(), - type: "http", - key: boardServerKey, - }; - } else { - this.#toast( - "No Board Server API key provided", - BreadboardUI.Events.ToastType.WARNING - ); - } - } - - this.#runner = createRunner(config); - - this.#runObserver = new BreadboardUI.Utils.TopGraphObserver( - this.#runner, - this.#abortController.signal - ); - - this.#dataStore.releaseAll(); - this.#dataStore.createGroup("run"); - - this.#runner.addEventListener("end", () => { - this.stopRun(); - }); - - this.#runner.addEventListener("error", (event) => { - this.requestUpdate(); - if (event.data.code === 403) { - this.visitorStateManager.expireInvite(); - } - this.stopRun(); - }); - - this.#runner.addEventListener("input", async () => { - this.statusMessage = "Requesting user input"; - this.#statusMessageTime = null; - this.requestUpdate(); - }); - - this.#runner.addEventListener("nodeend", () => { - this.statusMessage = null; - this.#statusMessageTime = this.#formatter.format(Date.now()); - this.requestUpdate(); - }); - - this.#runner.addEventListener("nodestart", (evt) => { - this.statusMessage = evt.data.node.metadata?.description ?? null; - this.#statusMessageTime = this.#formatter.format(Date.now()); - this.requestUpdate(); - }); - - this.#runner.addEventListener("output", () => { - this.requestUpdate(); - }); - - this.#runner.addEventListener("pause", () => { - this.status = STATUS.PAUSED; - }); - - this.#runner.addEventListener("resume", () => { - this.status = STATUS.RUNNING; - }); - - this.#runner.addEventListener("secret", async () => { - const keys = this.#runner?.secretKeys(); - const secretsKeysNeeded = structuredClone(keys); - if (!secretsKeysNeeded) { - this.secretsNeeded = null; - return; - } - - const allKnownSecrets: [string, string][] = []; - for (let i = secretsKeysNeeded.length - 1; i >= 0; i--) { - const secret = secretsKeysNeeded[i]; - if (!secret) { - continue; - } - - const isConnection = secret.startsWith("connection:"); - if (isConnection) { - const grant = this.tokenVendor.getToken( - secret.slice("connection:".length) - ); - if (grant.state === "valid") { - allKnownSecrets.push([secret, grant.grant.access_token]); - secretsKeysNeeded.splice(i, 1); - } - } else { - const storedSecret = this.#getSecret(secret); - if (storedSecret) { - allKnownSecrets.push([secret, storedSecret]); - secretsKeysNeeded.splice(i, 1); - } - } - } - - if (secretsKeysNeeded.length === 0) { - const knownSecrets = Object.fromEntries(allKnownSecrets); - this.#runner?.run(knownSecrets); - } else { - this.secretsNeeded = secretsKeysNeeded; - } - }); - - this.#runner.addEventListener("start", () => { - this.status = STATUS.RUNNING; - this.#runStartTime = Date.now(); - }); - - this.#runner.run(); - } - - async #share() { - if (this.#isSharing) { - return; - } - - const graph = await this.#descriptorLoad; - if (!graph) { - return; - } - - const opts: Partial = { - url: window.location.href, - }; - - if (graph.title) { - opts.title = graph.title; - } - - if (graph.description) { - opts.text = graph.description; - } - - await navigator.share(opts); - this.#isSharing = false; - } - - #storeBoardServerKey(key: string) { - this.visitorStateManager.setBoardServerApiKey(key); - } - - #renderLoading() { - return html`
Loading...
`; - } - - #storeSecret(secret: string, value: string) { - globalThis.localStorage.setItem(`SECRET_${secret}`, value); - } - - #getSecret(secret: string) { - return globalThis.localStorage.getItem(`SECRET_${secret}`); - } - - #getSecrets(which: string[]): Record { - const secrets: Record = {}; - for (const secret of which) { - const storedSecret = globalThis.localStorage.getItem(`SECRET_${secret}`); - if (!storedSecret) { - this.#abortRun("Secret required, aborting run."); - throw new Error( - `Unexpected error - looking for secret ${secret} but unable to find it in storage` - ); - } - - secrets[secret] = storedSecret; - } - - return secrets; - } - - #toggleRunContext(evt: RunContextChangeEvent) { - this.runOnBoardServer = evt.where === "remote"; - globalThis.localStorage.setItem( - RUN_ON_BOARD_SERVER, - `${this.runOnBoardServer}` - ); - } - - #toast( - message: string, - type: BreadboardUI.Events.ToastType, - persistent = false, - id = globalThis.crypto.randomUUID() - ) { - this.#toasts.set(id, { message, type, persistent }); - this.requestUpdate(); - - return id; - } - - #abortRun(reason: string) { - this.#abortController?.abort(reason); - this.status = STATUS.STOPPED; - } - - render() { - const toasts = html`${map( - this.#toasts, - ([, { message, type, persistent }], idx) => { - const offset = this.#toasts.size - idx - 1; - return html``; - } - )}`; - - const boardTitle = Promise.all([this.#descriptorLoad, this.#kitLoad]).then( - ([graph, kits]) => { - if (!graph || !kits) { - return html`Failed to load`; - } - - return html`${graph.title}`; - } - ); - - const boardDescription = Promise.all([ - this.#descriptorLoad, - this.#kitLoad, - ]).then(([graph, kits]) => { - if (!graph || !kits) { - return html`Failed to load`; - } - - return graph.description ? html`${graph.description}` : nothing; - }); - - const log = this.#runObserver?.current()?.log ?? []; - const status = () => { - const classes: Record = { pending: false }; - const newest = log[log.length - 1]; - if (newest && (newest.type === "edge" || newest.type === "node")) { - classes.pending = newest.end === null; - } - - let message = html`Press "Start Activity" to begin`; - if (this.status !== STATUS.STOPPED) { - message = html`${this.statusMessage ?? "Working"}...`; - } - - const lastUpdateTime = new Promise((resolve) => { - setTimeout(resolve, 3000); - }).then(() => { - if (!this.#statusMessageTime || this.status === STATUS.STOPPED) { - return nothing; - } - - return html`Last update: ${this.#statusMessageTime}`; - }); - - return html`
- ${message}${until(lastUpdateTime)} -
`; - }; - - const active = - this.status === STATUS.RUNNING || this.status === STATUS.PAUSED; - - const activity = Promise.all([ - this.#descriptorLoad, - this.#kitLoad, - this.#visitorStateInit, - ]).then(() => { - return html` { - this.requestUpdate(); - }} - @bbinputenter=${(event: InputEnterEvent) => { - let data = event.data as InputValues; - const runner = this.#runner; - if (!runner) { - throw new Error("Can't send input, no runner"); - } - if (runner.running()) { - throw new Error("The runner is already running, cannot send input"); - } - runner.run(data); - }} - >`; - }); - - const nav = (popout: boolean) => { - return html` { - this.showMenu = false; - }} - @bbruncontextchange=${this.#toggleRunContext} - @bbshare=${this.#share} - @bbserverkeyrequest=${() => { - this.showServerKeyPopover = true; - }} - @bbinviterequest=${() => { - this.showInvitesPopover = true; - }} - ?visible=${popout && this.showMenu} - >`; - }; - - const inert = - this.secretsNeeded || - this.showMenu || - this.showServerKeyPopover || - this.showInvitesPopover; - - return html`
- ${nav(true)} -
-
-
- -

${until(boardTitle, this.#renderLoading())}

-
-

${until(boardDescription)}

- ${nav(false)} -
${this.#helpText()}
-
-
-
-
${until(activity)}
-
-
- - ${this.secretsNeeded - ? html` { - this.#abortRun("Secret not provided"); - this.secretsNeeded = null; - }} - @bbsekrits=${(evt: SecretsEnterEvent) => { - for (const [name, secret] of Object.entries(evt.sekrits)) { - this.#storeSecret(name, secret); - } - - const secrets = this.#getSecrets(this.secretsNeeded ?? []); - this.secretsNeeded = null; - this.#runner?.run(secrets); - }} - >` - : nothing} - ${this.showServerKeyPopover - ? html` { - this.showServerKeyPopover = false; - }} - @bbserverkeyenter=${(evt: BoardServerAPIKeyEnterEvent) => { - this.#storeBoardServerKey(evt.key); - this.showServerKeyPopover = false; - }} - >` - : nothing} - ${this.showInvitesPopover - ? html` { - this.showInvitesPopover = false; - }} - @bbtoast=${(evt: ToastEvent) => { - this.#toast(evt.message, evt.toastType); - }} - >` - : nothing} - -
- -
- ${status()} - -
-
- ${toasts}`; - } -} diff --git a/packages/board-server/src/app/elements/activity-log/activity-log-lite.ts b/packages/board-server/src/app/elements/activity-log/activity-log-lite.ts deleted file mode 100644 index ca1386c7cb3..00000000000 --- a/packages/board-server/src/app/elements/activity-log/activity-log-lite.ts +++ /dev/null @@ -1,817 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { - isLLMContent, - isLLMContentArray, - type ErrorObject, - type Schema, -} from "@google-labs/breadboard"; -import { - LitElement, - html, - css, - nothing, - type HTMLTemplateResult, - type PropertyValues, -} from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { map } from "lit/directives/map.js"; -import { until } from "lit/directives/until.js"; -import { type Ref, createRef, ref } from "lit/directives/ref.js"; -import { - type UserInputConfiguration, - type UserMessage, -} from "../../types/types.js"; -import { InputEnterEvent } from "../../events/events.js"; -import { classMap } from "lit/directives/class-map.js"; -import { - isImageURL, - isLLMContentArrayBehavior, - isLLMContentBehavior, -} from "../../utils/content-schema.js"; - -import * as BreadboardUI from "@breadboard-ai/shared-ui"; - -@customElement("bb-activity-log-lite-app") -export class ActivityLogLite extends LitElement { - @property() - start: number = 0; - - @property() - message: UserMessage | null = null; - - @property() - log: BreadboardUI.Types.LogEntry[] = []; - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: block; - padding-bottom: 60px; - } - - #controls { - position: sticky; - top: 0; - background: var(--bb-neutral-0); - display: grid; - grid-template-rows: 24px; - row-gap: var(--bb-grid-size-10); - align-items: center; - padding: var(--bb-grid-size-2) var(--bb-grid-size-2); - z-index: 1; - } - - #controls input { - border-radius: var(--bb-grid-size); - border: 1px solid var(--bb-neutral-300); - background: var(--bb-neutral-50); - width: 100%; - padding: var(--bb-grid-size-2); - height: 100%; - } - - #controls input:placeholder-shown { - background: var(--bb-neutral-50) var(--bb-icon-search) calc(100% - 5px) - center / 20px 20px no-repeat; - } - - #activity { - padding: var(--bb-grid-size-2); - } - - #actions { - display: flex; - justify-content: flex-end; - } - - #actions button { - border: none; - margin: 0 0 0 var(--bb-grid-size-8); - padding: 0 var(--bb-grid-size-8) 0 0; - height: 20px; - font: var(--bb-font-label-medium); - color: var(--bb-neutral-600); - transition: color 0.3s cubic-bezier(0, 0, 0.3, 1); - cursor: pointer; - } - - #actions button:focus, - #actions button:hover { - color: var(--bb-neutral-800); - transition-duration: 0.15s; - } - - #jump-to-bottom { - background: transparent var(--bb-icon-arrow-down-48px) right center / 24px - 24px no-repeat; - } - - #actions button:last-of-type { - margin-right: var(--bb-grid-size); - } - - #no-entries { - display: flex; - flex-direction: column; - align-items: center; - padding: var(--bb-grid-size-10) 0; - font: var(--bb-font-title-large); - color: var(--bb-neutral-400); - } - - .node-output { - margin: 0; - } - - .pending-input, - .edge { - padding: var(--bb-grid-size-4) var(--bb-grid-size-2) var(--bb-grid-size-4) - var(--bb-grid-size-16); - position: relative; - } - - .pending-input.newest, - .edge.newest { - animation: fadeAndSlideIn 0.3s cubic-bezier(0, 0, 0.3, 1) forwards; - } - - .edge.newest { - margin-bottom: var(--bb-grid-size-16); - } - - .edge.empty { - height: 0; - display: flex; - align-items: center; - color: var(--bb-neutral-600); - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - padding-top: var(--bb-grid-size-2); - padding-bottom: var(--bb-grid-size-2); - } - - .pending-input::before, - .edge::before { - content: ""; - position: absolute; - top: 0; - left: 40px; - height: 100%; - border-left: 1px solid var(--bb-neutral-300); - } - - .pending-input::after, - .edge::after { - content: ""; - position: absolute; - top: calc(50% - 14px); - left: 26px; - width: 28px; - height: 28px; - border: 1px solid var(--bb-neutral-300); - border-radius: 50%; - } - - .pending-input.newest::before, - .edge.newest::before { - transform: scaleY(0); - animation: growFromTop 0.3s cubic-bezier(0, 0, 0.3, 1) 0.2s forwards; - } - - .pending-input.newest::after, - .edge.newest::after { - opacity: 0; - animation: fadeAndSlideIn 0.3s cubic-bezier(0, 0, 0.3, 1) 0.4s forwards; - } - - .pending-input::after { - background: var(--bb-neutral-0) var(--bb-icon-input) center center / 20px - 20px no-repeat; - } - - .edge::after { - background: var(--bb-neutral-0) var(--bb-icon-output) center center / 20px - 20px no-repeat; - } - - .edge.empty::after { - display: none; - } - - .edge.empty.newest::before { - display: none; - } - - .edge bb-llm-output, - .edge bb-llm-output-array { - margin-bottom: 0; - } - - .pending-input:last-of-type::before, - .edge:last-of-type::before { - height: 50%; - } - - .entry { - position: relative; - border: 1px solid var(--bb-neutral-200); - border-radius: var(--bb-grid-size-10); - padding: var(--bb-grid-size-2) var(--bb-grid-size-3); - width: 50%; - animation: fadeAndSlideIn 0.3s cubic-bezier(0, 0, 0.3, 1) forwards; - } - - .entry.pending::after { - content: ""; - position: absolute; - left: calc(100% + var(--bb-grid-size-2)); - top: calc(50% - 8px); - width: 16px; - height: 16px; - background: url(/images/progress-ui.svg) center center / 16px 16px - no-repeat; - } - - .entry:not(.pending)::after { - content: attr(completed); - position: absolute; - left: calc(100% + var(--bb-grid-size-2)); - top: calc(50% - 8px); - height: 16px; - color: var(--bb-neutral-600); - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - width: auto; - min-width: 150px; - } - - .entry.hidden { - display: none; - } - - .entry { - display: flex; - align-items: flex-start; - list-style: none; - font: var(--bb-font-title-small); - color: var(--bb-neutral-600); - user-select: none; - } - - .entry::before { - content: ""; - width: 20px; - height: 20px; - background: var(--bb-ui-50) var(--bb-icon-generic-node) center center / - 20px 20px no-repeat; - border-radius: 50%; - margin-right: var(--bb-grid-size-2); - } - - .entry.input::before { - background: var(--bb-icon-input) center center / 20px 20px no-repeat; - } - - .entry.output::before { - background: var(--bb-icon-output) center center / 20px 20px no-repeat; - } - - .entry.secret::before { - background: var(--bb-icon-password) center center / 20px 20px no-repeat; - } - - .entry.specialist { - color: var(--bb-ui-500); - } - - .entry.specialist::before { - background: var(--bb-icon-smart-toy) center center / 20px 20px no-repeat; - } - - .entry.human, - .entry.user { - color: var(--bb-human-500); - } - - .entry.human::before, - .entry.user::before { - background: var(--bb-icon-human) center center / 20px 20px no-repeat; - } - - .entry.looper { - color: var(--bb-looper-500); - } - - .entry.looper::before { - background: var(--bb-icon-lightbulb) center center / 20px 20px no-repeat; - } - - .entry.joiner { - color: var(--bb-looper-500); - } - - .entry.joiner::before { - background: var(--bb-icon-merge-type) center center / 20px 20px no-repeat; - } - - .entry.runjavascript { - color: var(--bb-nodes-700); - } - - .entry.runjavascript::before { - background: var(--bb-nodes-400) var(--bb-icon-javascript) center center / - 20px 20px no-repeat; - } - - .entry .no-information { - font: var(--bb-font-label-medium); - color: var(--bb-neutral-600); - width: 100%; - text-align: center; - margin-top: var(--bb-grid-size); - } - - .continue-button { - background: var(--bb-ui-100) var(--bb-icon-resume-blue) 8px 4px / 16px - 16px no-repeat; - color: var(--bb-ui-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4) 0 var(--bb-grid-size-7); - margin: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - } - - .completed-item .title { - display: block; - font: 600 var(--bb-label-medium) / var(--bb-label-line-height-medium) - var(--bb-font-family); - padding: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - } - - .completed-item .description { - display: block; - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - margin: 0 0 var(--bb-grid-size-2) 0; - max-width: 90%; - } - - .error { - display: flex; - background: var(--bb-warning-50); - border: 2px solid var(--bb-warning-100); - padding: var(--bb-grid-size-3); - border-radius: var(--bb-grid-size-2); - color: var(--bb-warning-700); - overflow: auto; - font: var(--bb-font-body-small); - font-family: var(--bb-font-family-mono); - } - - @media (min-width: 700px) { - #controls { - grid-template-rows: 24px; - padding: var(--bb-grid-size-3) var(--bb-grid-size-2) - var(--bb-grid-size-3) 0; - } - - #activity { - padding: var(--bb-grid-size-2) var(--bb-grid-size-2) - var(--bb-grid-size-2) 0; - } - } - - @media (min-width: 1120px) { - #controls { - grid-template-rows: 24px; - padding: var(--bb-grid-size-3) 0; - } - - #controls input { - height: 42px; - } - - #activity { - padding: var(--bb-grid-size-2) 0; - } - } - - @keyframes fadeAndSlideIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } - } - - @keyframes growFromTop { - from { - transform-origin: 0 0; - transform: scale(1, 0); - } - - to { - transform-origin: 0 0; - transform: scale(1, 1); - } - } - `; - - #jumpToBottomAfterUpdated = false; - #formatter = new Intl.DateTimeFormat(navigator.languages, { - month: "long", - day: "numeric", - hour: "numeric", - minute: "2-digit", - hour12: true, - }); - #userInputRef: Ref = createRef(); - #activityRef: Ref = createRef(); - - async #renderPendingInput(event: BreadboardUI.Types.EdgeLogEntry) { - const schema = event.schema as Schema; - if (!schema) { - return html`Unable to render`; - } - - const requiredFields = schema.required ?? []; - - // TODO: Implement support for multiple iterations over the - // same input over a run. Currently, we will only grab the - // first value. - const userInputs: UserInputConfiguration[] = Object.entries( - schema.properties ?? {} - ).reduce((prev, [name, schema]) => { - let value = undefined; - if (schema.type === "object") { - if (isLLMContentBehavior(schema)) { - if (!isLLMContent(value)) { - value = undefined; - } - } else { - value = JSON.stringify(value, null, 2); - } - } - - if (schema.type === "array") { - if (isLLMContentArrayBehavior(schema)) { - if (!isLLMContentArray(value)) { - value = undefined; - } - } else { - value = JSON.stringify(value, null, 2); - } - } - - prev.push({ - name, - title: schema.title ?? name, - secret: false, - schema, - configured: false, - required: requiredFields.includes(name), - value, - }); - - return prev; - }, [] as UserInputConfiguration[]); - - const continueRun = () => { - if (!this.#userInputRef.value) { - return; - } - - const outputs = this.#userInputRef.value.processData(true); - if (!outputs) { - return; - } - - this.dispatchEvent( - new InputEnterEvent(event.id!, outputs, /* allowSavingIfSecret */ true) - ); - }; - - return html` { - const isMac = navigator.platform.indexOf("Mac") === 0; - const isCtrlCommand = isMac ? evt.metaKey : evt.ctrlKey; - - if (!(evt.key === "Enter" && isCtrlCommand)) { - return; - } - - continueRun(); - }} - > - `; - } - - async #renderCompletedInputOrOutput(event: BreadboardUI.Types.EdgeLogEntry) { - const { value, schema } = event; - const type = event.id ? "input" : "output"; - if (!value) { - return html`Unable to render item`; - } - - const properties = schema?.properties ?? {}; - - return html`
- ${Object.entries(value).map(([name, nodeValue]) => { - let value: HTMLTemplateResult | symbol = nothing; - if (typeof nodeValue === "object") { - if (isLLMContentArray(nodeValue)) { - value = html``; - } else if (isLLMContent(nodeValue)) { - if (!nodeValue.parts) { - // Special case for "$metadata" item. - // See https://github.com/breadboard-ai/breadboard/issues/1673 - // TODO: Make this not ugly. - const data = (nodeValue as unknown as { data: unknown }).data; - value = html``; - } - - if (!nodeValue.parts.length) { - value = html`No data provided`; - } - - value = nodeValue.parts.length - ? html`` - : html`No data provided`; - } else if (isImageURL(nodeValue)) { - value = html``; - } else { - value = html``; - } - } else { - let renderableValue: HTMLTemplateResult | symbol = nothing; - const format = properties[name]?.format; - if ( - format && - format === "markdown" && - typeof nodeValue === "string" - ) { - renderableValue = html`${BreadboardUI.Directives.markdown( - nodeValue - )}`; - } else { - renderableValue = html`${nodeValue !== undefined - ? nodeValue - : "No value provided"}`; - } - - // prettier-ignore - value = html`
${renderableValue}
`; - } - - let title: HTMLTemplateResult | symbol = nothing; - let description: HTMLTemplateResult | symbol = nothing; - if (schema && schema.properties) { - title = html`${schema.properties[name]?.title ?? `Input`}`; - - if (schema.properties[name]?.description) { - description = html`${schema.properties[name]?.description}`; - } - } - - return type === "input" - ? html`
- - ${value} -
` - : html`${value}`; - })} -
`; - } - - #renderLog(entries: BreadboardUI.Types.LogEntry[]) { - return html`${map(entries, (entry, idx) => { - const newest = idx === entries.length - 1; - switch (entry.type) { - case "edge": { - const pending = entry.end === null; - - if (entry.id) { - // The "input" edge will have an id - // TODO: Maybe we should just have different types of edges? - if (entry.end !== null) { - return html`
- ${until(this.#renderCompletedInputOrOutput(entry))} -
`; - } - return html`
- ${until(this.#renderPendingInput(entry))} -
`; - } - - if (entry.value) { - // The "output" edge will have no id, but will have a value. - return html`
- ${until(this.#renderCompletedInputOrOutput(entry))} -
`; - } - - return html`
`; - } - - case "node": { - const { descriptor, end } = entry; - const { type } = descriptor; - const icon = undefined; - - let content: - | HTMLTemplateResult - | Promise - | symbol = nothing; - - const classes: Record = { - entry: true, - pending: end === null, - }; - - classes[type.toLocaleLowerCase()] = true; - classes.pending = end === null; - if (icon) { - classes[icon] = true; - } - - let completed = null; - if (end !== null) { - completed = this.#formatter.format(this.start + end); - } - - return html`
- ${entry.title()} -
- ${content}`; - } - - case "error": { - const { error } = entry; - let output = ""; - if (typeof error === "string") { - output = error; - } else { - if ((error.error as Error)?.name === "AbortError") { - console.log("💖 actually aborted"); - } - if (typeof error.error === "string") { - output = error.error; - } else { - let messageOutput = ""; - let errorData = error; - while (typeof errorData === "object") { - if (errorData && "message" in errorData) { - messageOutput += `${errorData.message}\n`; - } - - errorData = errorData.error as ErrorObject; - } - - output = messageOutput; - } - } - - return html`
${output}
`; - } - } - })}`; - } - - #jumpToBottom() { - if (!this.#activityRef.value) { - return; - } - - const entries = - this.#activityRef.value.querySelectorAll(".entry"); - if (entries.length === 0) { - return; - } - - const entry = entries[entries.length - 1]; - if (!entry) { - return; - } - entry.scrollIntoView({ - behavior: "smooth", - block: "start", - inline: "nearest", - }); - } - - protected willUpdate(changedProperties: PropertyValues): void { - if (!changedProperties.has("log")) { - return; - } - - this.#jumpToBottomAfterUpdated = true; - } - - protected updated(): void { - if (!this.#jumpToBottomAfterUpdated) { - return; - } - - this.#jumpToBottomAfterUpdated = false; - requestAnimationFrame(() => { - this.#jumpToBottom(); - }); - } - - render() { - return html`
-
- ${this.log.length - ? html`` - : nothing} -
-
-
- ${this.log.length - ? this.#renderLog(this.log) - : html`
- - - ${this.message?.alt} - -

No activity information

-
`} -
`; - } -} diff --git a/packages/board-server/src/app/elements/board-server-key/board-server-key.ts b/packages/board-server/src/app/elements/board-server-key/board-server-key.ts deleted file mode 100644 index 621d2611d89..00000000000 --- a/packages/board-server/src/app/elements/board-server-key/board-server-key.ts +++ /dev/null @@ -1,209 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { LitElement, html, css, type PropertyValues } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { createRef, ref, type Ref } from "lit/directives/ref.js"; -import { - BoardServerAPIKeyEnterEvent, - OverlayDismissEvent, -} from "../../events/events.js"; - -@customElement("bb-board-server-key") -export class BoardServerKey extends LitElement { - @property() - key: string | null = null; - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: flex; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.05); - position: fixed; - top: 0; - z-index: 100; - align-items: center; - animation: fadeIn 0.3s cubic-bezier(0, 0, 0.3, 1) forwards; - } - - dialog { - background: var(--bb-neutral-0); - width: 80vw; - max-width: 360px; - border: none; - border-radius: var(--bb-grid-size-2); - padding: var(--bb-grid-size-3); - } - - dialog h1 { - font: var(--bb-font-title-small); - font-weight: 500; - margin: 0 0 var(--bb-grid-size-2) 0; - padding-left: var(--bb-grid-size-6); - background: transparent var(--bb-icon-password) 0 center / 20px 20px - no-repeat; - } - - .secret { - display: flex; - flex-direction: column; - margin-bottom: var(--bb-grid-size-2); - } - - .secret label { - display: block; - font: 600 var(--bb-label-medium) / var(--bb-label-line-height-medium) - var(--bb-font-family); - padding: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - } - - .secret input { - display: block; - width: 100%; - border-radius: var(--bb-grid-size); - background: var(--bb-neutral-0); - padding: var(--bb-grid-size-2); - border: 1px solid var(--bb-neutral-300); - - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family-mono); - } - - #continue { - background: var(--bb-ui-100) var(--bb-icon-resume-blue) 8px 4px / 16px - 16px no-repeat; - color: var(--bb-ui-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4) 0 var(--bb-grid-size-7); - margin: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - } - - #cancel { - background: var(--bb-neutral-100); - color: var(--bb-neutral-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4); - margin: var(--bb-grid-size-2) 0 var(--bb-grid-size) var(--bb-grid-size); - } - - @keyframes fadeIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } - } - `; - - #formRef: Ref = createRef(); - #onKeyDownBound = this.#onKeyDown.bind(this); - #onClickBound = this.#onClick.bind(this); - - connectedCallback(): void { - super.connectedCallback(); - window.addEventListener("keydown", this.#onKeyDownBound); - window.addEventListener("click", this.#onClickBound); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - window.removeEventListener("keydown", this.#onKeyDownBound); - window.removeEventListener("click", this.#onClickBound); - } - - #onKeyDown(evt: KeyboardEvent) { - if (evt.key === "Escape") { - this.dispatchEvent(new OverlayDismissEvent()); - return; - } - - const isMac = navigator.platform.indexOf("Mac") === 0; - const isCtrlCommand = isMac ? evt.metaKey : evt.ctrlKey; - - if (evt.key === "Enter" && isCtrlCommand && this.#formRef.value) { - this.#formRef.value.dispatchEvent(new SubmitEvent("submit")); - } - } - - #onClick() { - this.dispatchEvent(new OverlayDismissEvent()); - } - - protected firstUpdated(): void { - if (!this.#formRef.value) { - return; - } - - const input = this.#formRef.value.querySelector("input"); - if (!input) { - return; - } - - input.select(); - } - - render() { - return html` { - evt.stopImmediatePropagation(); - }} - > -

Please enter your Board Server API key

-
{ - if (!this.#formRef.value) { - return; - } - - const el = - this.#formRef.value.querySelector(`#server-key`); - - if (!el) { - return; - } - - const key = el.value ?? ""; - this.dispatchEvent(new BoardServerAPIKeyEnterEvent(key)); - }} - > -
- - -
- - - - -
`; - } -} diff --git a/packages/board-server/src/app/elements/elements.ts b/packages/board-server/src/app/elements/elements.ts deleted file mode 100644 index 43ed6e573f0..00000000000 --- a/packages/board-server/src/app/elements/elements.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export { ActivityLogLite } from "./activity-log/activity-log-lite.js"; -export { AppNav } from "./nav/nav.js"; -export { BoardServerKey } from "./board-server-key/board-server-key.js"; -export { BoardInvites } from "./invites/invites.js"; -export { SecretRequester } from "./secret/secret.js"; diff --git a/packages/board-server/src/app/elements/invites/invites.ts b/packages/board-server/src/app/elements/invites/invites.ts deleted file mode 100644 index 1b34353af58..00000000000 --- a/packages/board-server/src/app/elements/invites/invites.ts +++ /dev/null @@ -1,342 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { LitElement, html, css, nothing, type TemplateResult } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { OverlayDismissEvent, ToastEvent } from "../../events/events.js"; -import { - VisitorStateManager, - visitorStateManagerContext, -} from "../../utils/visitor-state-manager.js"; -import { until } from "lit/directives/until.js"; -import { map } from "lit/directives/map.js"; -import * as BreadboardUI from "@breadboard-ai/shared-ui"; -import { consume } from "@lit/context"; - -@customElement("bb-board-invites") -export class BoardInvites extends LitElement { - @consume({ context: visitorStateManagerContext }) - @property({ attribute: false }) - public visitorStateManager?: VisitorStateManager; - - @property() - key: string | null = null; - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: flex; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.05); - position: fixed; - top: 0; - z-index: 100; - align-items: center; - animation: fadeIn 0.3s cubic-bezier(0, 0, 0.3, 1) forwards; - } - - dialog { - background: var(--bb-neutral-0); - width: 80vw; - max-width: 360px; - border: none; - border-radius: var(--bb-grid-size-2); - padding: var(--bb-grid-size-3); - } - - dialog h1 { - font: var(--bb-font-title-small); - font-weight: 500; - margin: 0 0 var(--bb-grid-size-2) 0; - padding-left: var(--bb-grid-size-6); - background: transparent var(--bb-icon-rsvp) 0 center / 20px 20px no-repeat; - } - - .create-invite { - background: var(--bb-ui-100) var(--bb-icon-rsvp) 8px 4px / 16px 16px - no-repeat; - color: var(--bb-ui-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4) 0 var(--bb-grid-size-7); - margin: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - cursor: pointer; - } - - #cancel { - background: var(--bb-neutral-100); - color: var(--bb-neutral-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4); - margin: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - cursor: pointer; - } - - #loading { - padding-left: var(--bb-grid-size-8); - background: url(/images/progress-ui.svg) left center / 16px 16px no-repeat; - } - - #invite-listing { - margin: var(--bb-grid-size-2) 0; - padding: 0; - list-style: none; - } - - #invite-listing li { - margin-bottom: var(--bb-grid-size-2); - border-radius: var(--bb-grid-size); - background: var(--bb-ui-50); - display: flex; - align-items: center; - padding: var(--bb-grid-size-2) var(--bb-grid-size-3); - } - - #invite-listing .delete { - height: 24px; - width: 24px; - font-size: 0; - background: var(--bb-neutral-0) var(--bb-icon-delete) center center / 16px - 16px no-repeat; - flex: 0 0 auto; - border: none; - border-radius: 50%; - opacity: 0.5; - transition: opacity 0.3s cubic-bezier(0, 0, 0.3, 1); - cursor: pointer; - margin-right: var(--bb-grid-size-2); - } - - #invite-listing .delete:hover, - #invite-listing .delete:focus { - transition-duration: 0.1s; - opacity: 1; - } - - #invite-listing .copy-to-clipboard { - height: 24px; - width: 24px; - font-size: 0; - background: var(--bb-neutral-0) var(--bb-icon-copy-to-clipboard) center - center / 16px 16px no-repeat; - flex: 0 0 auto; - border: none; - border-radius: 50%; - opacity: 0.5; - transition: opacity 0.3s cubic-bezier(0, 0, 0.3, 1); - cursor: pointer; - } - - #invite-listing .copy-to-clipboard:hover, - #invite-listing .copy-to-clipboard:focus { - transition-duration: 0.1s; - opacity: 1; - } - - .label { - flex: 1; - } - - .code { - font: var(--bb-font-title-small); - font-weight: 500; - font-family: var(--bb-font-family-mono); - } - - @keyframes fadeIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } - } - `; - - #onKeyDownBound = this.#onKeyDown.bind(this); - #onClickBound = this.#onClick.bind(this); - - #loadInvites: Promise> | undefined; - #creating = false; - #deleting = false; - #copying = false; - - connectedCallback(): void { - super.connectedCallback(); - window.addEventListener("keydown", this.#onKeyDownBound); - window.addEventListener("click", this.#onClickBound); - this.#loadInvites = this.#refreshInviteList(); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - window.removeEventListener("keydown", this.#onKeyDownBound); - window.removeEventListener("click", this.#onClickBound); - } - - #onKeyDown(evt: KeyboardEvent) { - if (evt.key !== "Escape") { - return; - } - - this.dispatchEvent(new OverlayDismissEvent()); - } - - #onClick() { - this.dispatchEvent(new OverlayDismissEvent()); - } - - #refreshInviteList() { - return this.visitorStateManager - ?.canCreateInvite() - .then(async (canCreate) => { - if (!canCreate) { - return html`
-

- You are not able to manage invites for this board. You can only - manage invites for boards you created. -

-
`; - } - - const listing = (await this.visitorStateManager?.listInvites()) || { - success: false, - }; - if (!listing.success) { - return html`
Unable to load invites
`; - } - - return html`
- ${listing.invites.length > 0 - ? html`
    - ${map(listing.invites, (invite) => { - return html`
  • -
    - Invite code: ${invite} -
    - - -
  • `; - })} -
` - : html`

There are no active invites for this board

- `} -
`; - }); - } - - render() { - return html` { - evt.stopImmediatePropagation(); - }} - > -

Manage invites

- ${until( - this.#loadInvites, - html`
Loading invites...
` - )} - - -
`; - } -} diff --git a/packages/board-server/src/app/elements/nav/nav.ts b/packages/board-server/src/app/elements/nav/nav.ts deleted file mode 100644 index d3b88bce6b4..00000000000 --- a/packages/board-server/src/app/elements/nav/nav.ts +++ /dev/null @@ -1,306 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { LitElement, html, css, nothing } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { - BoardServerKeyRequestEvent, - DismissMenuEvent, - InviteRequestEvent, - RunContextChangeEvent, - ShareEvent, -} from "../../events/events.js"; -import { VisitorState } from "../../utils/types.js"; - -@customElement("bb-app-nav") -export class AppNav extends LitElement { - @property({ reflect: true, type: Boolean }) - popout = true; - - @property({ reflect: false }) - visitorState: VisitorState = VisitorState.LOADING; - - @property({ reflect: false }) - shareTitle: string | null = null; - - @property({ reflect: false }) - shareText: string | null = null; - - @property({ reflect: false }) - runOnBoardServer = false; - - @property({ reflect: false }) - boardKeyNeeded = false; - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: block; - } - - :host([popout]) #container { - transition: transform 0.3s cubic-bezier(0, 0, 0.3, 1); - transform: translateX(-100%) translateX(-10px); - height: 100%; - border-right: 1px solid var(--bb-neutral-300); - padding: var(--bb-grid-size-2); - } - - :host([visible]) #container { - pointer-events: auto; - transform: translateX(0); - } - - :host([popout]) { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - pointer-events: none; - width: 100%; - height: 100%; - overflow: hidden; - z-index: 100; - } - - :host(:not([popout])) { - margin-top: 30px; - padding-top: 30px; - border-top: 1px solid var(--bb-neutral-300); - } - - :host([popout]) #container { - width: 80%; - background: var(--bb-neutral-0); - } - - #background { - background: transparent; - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - pointer-events: none; - } - - :host(:not([popout])) #background { - display: none; - } - - :host([visible]) #background { - pointer-events: auto; - } - - #container h1 { - margin: 0; - padding: var(--bb-grid-size-2) 0; - font: var(--bb-font-title-medium); - } - - #container ul { - margin: 0; - list-style: none; - padding: 0; - } - - :host(:not([popout])) #container ul { - padding-left: var(--bb-grid-size-4); - } - - #container li { - min-height: 24px; - display: flex; - flex-direction: column; - justify-content: center; - margin-bottom: var(--bb-grid-size-2); - align-items: flex-start; - } - - button, - a, - label { - background: transparent; - border: none; - cursor: pointer; - padding: 0 0 0 var(--bb-grid-size-8); - color: var(--bb-neutral-800); - font: var(--bb-font-label-medium); - text-decoration: none; - } - - button .text, - a .text, - label .text { - opacity: 0.6; - transition: opacity 0.3s cubic-bezier(0, 0, 0.3, 1); - } - - button:hover .text, - button:focus .text, - a:hover .text, - a:focus .text, - label:hover .text, - label:focus .text { - opacity: 1; - } - - button#update-board-key { - background: transparent var(--bb-icon-password) left center / 20px 20px - no-repeat; - } - - button#share { - background: transparent var(--bb-icon-share) left center / 20px 20px - no-repeat; - } - - button#create-invite { - background: transparent var(--bb-icon-rsvp) left center / 20px 20px - no-repeat; - } - - button#list-invites { - background: transparent var(--bb-icon-list) left center / 20px 20px - no-repeat; - } - - a#visual-editor { - background: transparent var(--bb-icon-open-new) left center / 20px 20px - no-repeat; - } - - #run-on-board-server { - display: none; - } - - label[for="run-on-board-server"] { - padding-left: var(--bb-grid-size-8); - background: transparent var(--bb-icon-toggle-off) left center / 20px 20px - no-repeat; - } - - #run-on-board-server:checked ~ label[for="run-on-board-server"] { - background: transparent var(--bb-icon-toggle-on) left center / 20px 20px - no-repeat; - } - - #key-needed { - margin: var(--bb-grid-size-2) 0; - } - - #key-needed button { - padding: var(--bb-grid-size-2) var(--bb-grid-size-3); - background: var(--bb-boards-100); - color: var(--bb-boards-700); - text-align: center; - border-radius: var(--bb-grid-size); - border: none; - font: var(--bb-font-label-medium); - opacity: 0.85; - } - `; - - render() { - const boardUrl = window.location.href.replace(/app$/, "json"); - const visualEditorUrl = `https://breadboard-ai.web.app/?board=${boardUrl}`; - - const runOnBoardServer = - this.visitorState === VisitorState.VISITOR - ? nothing - : html`
  • - { - if (!(evt.target instanceof HTMLInputElement)) { - return; - } - - this.dispatchEvent( - new RunContextChangeEvent( - evt.target.checked ? "remote" : "local" - ) - ); - }} - /> -
  • `; - - const manageInvites = - this.visitorState === VisitorState.OWNER - ? html`
  • - -
  • ` - : nothing; - - const boardServerKeyText = - this.visitorState >= VisitorState.USER - ? "Update Board Server API Key" - : "Sign in to Board Server"; - - const showShare = "share" in navigator; - return html`
    { - this.dispatchEvent(new DismissMenuEvent()); - }} - >
    -
    { - evt.stopImmediatePropagation(); - }} - > - ${this.popout ? html`

    Menu

    ` : nothing} -
      -
    • - Open in Visual Editor -
    • - ${this.visitorState === VisitorState.LOADING - ? nothing - : html` ${runOnBoardServer} -
    • - -
    • - ${manageInvites}`} - ${showShare - ? html`
    • - -
    • ` - : nothing} -
    -
    `; - } -} diff --git a/packages/board-server/src/app/elements/secret/secret.ts b/packages/board-server/src/app/elements/secret/secret.ts deleted file mode 100644 index 8c9d0972b55..00000000000 --- a/packages/board-server/src/app/elements/secret/secret.ts +++ /dev/null @@ -1,226 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { LitElement, html, css } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { createRef, ref, type Ref } from "lit/directives/ref.js"; -import { OverlayDismissEvent, SecretsEnterEvent } from "../../events/events.js"; - -@customElement("bb-secret-requester") -export class SecretRequester extends LitElement { - @property() - secrets: string[] = []; - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: flex; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.05); - position: fixed; - top: 0; - z-index: 100; - align-items: center; - animation: fadeIn 0.3s cubic-bezier(0, 0, 0.3, 1) forwards; - } - - dialog { - background: var(--bb-neutral-0); - width: 80vw; - max-width: 300px; - border: none; - border-radius: var(--bb-grid-size-2); - padding: var(--bb-grid-size-3); - } - - dialog h1 { - font: var(--bb-font-title-small); - margin: 0 0 var(--bb-grid-size-2) 0; - padding-left: var(--bb-grid-size-6); - background: transparent var(--bb-icon-password) 0 center / 20px 20px - no-repeat; - } - - .secret { - display: flex; - flex-direction: column; - margin-bottom: var(--bb-grid-size-2); - } - - .secret label { - display: block; - font: 600 var(--bb-label-medium) / var(--bb-label-line-height-medium) - var(--bb-font-family); - padding: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - } - - .secret input { - display: block; - width: 100%; - border-radius: var(--bb-grid-size); - background: var(--bb-neutral-0); - padding: var(--bb-grid-size-2); - border: 1px solid var(--bb-neutral-300); - - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family-mono); - } - - #continue { - background: var(--bb-ui-100) var(--bb-icon-resume-blue) 8px 4px / 16px - 16px no-repeat; - color: var(--bb-ui-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4) 0 var(--bb-grid-size-7); - margin: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - } - - #cancel { - background: var(--bb-neutral-100); - color: var(--bb-neutral-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4); - margin: var(--bb-grid-size-2) 0 var(--bb-grid-size) var(--bb-grid-size); - } - - @keyframes fadeIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } - } - `; - - #formRef: Ref = createRef(); - - #onKeyDownBound = this.#onKeyDown.bind(this); - #onClickBound = this.#onClick.bind(this); - - connectedCallback(): void { - super.connectedCallback(); - window.addEventListener("keydown", this.#onKeyDownBound); - window.addEventListener("click", this.#onClickBound); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - window.removeEventListener("keydown", this.#onKeyDownBound); - window.removeEventListener("click", this.#onClickBound); - } - - #onKeyDown(evt: KeyboardEvent) { - if (evt.key === "Escape") { - this.dispatchEvent(new OverlayDismissEvent()); - return; - } - - const isMac = navigator.platform.indexOf("Mac") === 0; - const isCtrlCommand = isMac ? evt.metaKey : evt.ctrlKey; - - if (evt.key === "Enter" && isCtrlCommand && this.#formRef.value) { - this.#formRef.value.dispatchEvent(new SubmitEvent("submit")); - } - } - - #onClick() { - this.dispatchEvent(new OverlayDismissEvent()); - } - - protected firstUpdated(): void { - if (!this.#formRef.value) { - return; - } - - const input = this.#formRef.value.querySelector("input"); - if (!input) { - return; - } - - input.select(); - } - - render() { - return html` { - evt.stopImmediatePropagation(); - }} - > -

    Please enter the following secrets

    -
    { - if (!this.#formRef.value) { - return; - } - - if (!this.#formRef.value.checkValidity()) { - this.#formRef.value.reportValidity(); - return; - } - - const values: [string, string][] = this.secrets.map((secret) => { - if (!this.#formRef.value) { - return [secret, ""]; - } - - const el = this.#formRef.value.querySelector( - `#${secret}` - ); - if (!el) { - return [secret, ""]; - } - - return [secret, el.value]; - }); - - this.dispatchEvent(new SecretsEnterEvent(Object.fromEntries(values))); - }} - > - ${this.secrets.map((secret) => { - if (secret.startsWith("connection:")) { - return html``; - } - return html`
    - - -
    `; - })} - - - - -
    `; - } -} diff --git a/packages/board-server/src/app/events/events.ts b/packages/board-server/src/app/events/events.ts deleted file mode 100644 index 55615dd6417..00000000000 --- a/packages/board-server/src/app/events/events.ts +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type * as BreadboardUI from "@breadboard-ai/shared-ui"; - -const eventInit = { - bubbles: true, - cancelable: true, - composed: true, -}; - -export class InputEnterEvent extends Event { - static eventName = "bbinputenter"; - - constructor( - public readonly id: string, - public readonly data: Record, - public readonly allowSavingIfSecret: boolean - ) { - super(InputEnterEvent.eventName, { ...eventInit }); - } -} - -export class DismissMenuEvent extends Event { - static eventName = "bbdismissmenu"; - - constructor() { - super(DismissMenuEvent.eventName, { ...eventInit }); - } -} - -export class OverlayDismissEvent extends Event { - static eventName = "bboverlaydismiss"; - - constructor() { - super(OverlayDismissEvent.eventName, { ...eventInit }); - } -} - -export class ShareEvent extends Event { - static eventName = "bbshare"; - - constructor() { - super(ShareEvent.eventName, { ...eventInit }); - } -} - -export class SecretsEnterEvent extends Event { - static eventName = "bbsekrits"; - - constructor(public readonly sekrits: Record) { - super(SecretsEnterEvent.eventName, { ...eventInit }); - } -} - -export class BoardServerAPIKeyEnterEvent extends Event { - static eventName = "bbserverkeyenter"; - - constructor(public readonly key: string) { - super(BoardServerAPIKeyEnterEvent.eventName, { ...eventInit }); - } -} - -export class BoardServerKeyRequestEvent extends Event { - static eventName = "bbserverkeyrequest"; - - constructor() { - super(BoardServerKeyRequestEvent.eventName, { ...eventInit }); - } -} - -export class RunContextChangeEvent extends Event { - static eventName = "bbruncontextchange"; - - constructor(public readonly where: "remote" | "local") { - super(RunContextChangeEvent.eventName, { ...eventInit }); - } -} - -export class InviteRequestEvent extends Event { - static eventName = "bbinviterequest"; - - constructor() { - super(InviteRequestEvent.eventName, { ...eventInit }); - } -} - -export class ToastEvent extends Event { - static eventName = "bbtoast"; - - constructor( - public readonly message: string, - public readonly toastType: BreadboardUI.Events.ToastType - ) { - super(ToastEvent.eventName, { ...eventInit }); - } -} diff --git a/packages/board-server/src/app/types/types.ts b/packages/board-server/src/app/types/types.ts deleted file mode 100644 index c91cfd3df5c..00000000000 --- a/packages/board-server/src/app/types/types.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - InputValues, - NodeConfiguration, - NodeValue, - PortStatus, - Schema, -} from "@google-labs/breadboard"; - -export type InputCallback = (data: InputValues) => void; - -export enum STATUS { - RUNNING = "running", - PAUSED = "paused", - STOPPED = "stopped", -} - -export type UserInputConfiguration = { - name: string; - title: string; - secret: boolean; - required?: boolean; - configured?: boolean; - value?: NodeValue; - schema?: Schema; - status?: PortStatus; - type?: Schema["type"]; -}; - -export type UserOutputValues = NodeConfiguration; - -export interface AllowedLLMContentTypes { - audioFile: boolean; - audioMicrophone: boolean; - videoFile: boolean; - videoWebcam: boolean; - imageFile: boolean; - imageWebcam: boolean; - imageDrawable: boolean; - textFile: boolean; - textInline: boolean; -} - -export interface UserMessage { - srcset: string; - src: string; - alt: string; -} diff --git a/packages/board-server/src/app/utils/content-schema.ts b/packages/board-server/src/app/utils/content-schema.ts deleted file mode 100644 index b9c27433cf6..00000000000 --- a/packages/board-server/src/app/utils/content-schema.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - type NodeValue, - type Schema, - type UnresolvedPathBoardCapability, -} from "@google-labs/breadboard"; - -export const isBoardBehavior = ( - schema: Schema, - value: NodeValue -): value is UnresolvedPathBoardCapability | string | undefined => { - if (!schema.behavior?.includes("board")) return false; - if (!value) return true; - if (typeof value === "string") return true; - if (typeof value === "object") { - const maybeCapability = value as UnresolvedPathBoardCapability; - return maybeCapability.kind === "board" && !!maybeCapability.path; - } - return false; -}; - -export function isPortSpecBehavior(schema: Schema) { - return schema.behavior?.includes("ports-spec"); -} - -export function isCodeBehavior(schema: Schema) { - return schema.behavior?.includes("code"); -} - -export function isLLMContentBehavior(schema: Schema) { - return schema.behavior?.includes("llm-content"); -} - -export function isLLMContentArrayBehavior(schema: Schema) { - if (schema.type !== "array") return false; - if (Array.isArray(schema.items)) return false; - if (schema.items?.type !== "object") return false; - if (!schema.items?.behavior?.includes("llm-content")) return false; - - return true; -} - -export function isImageURL( - nodeValue: unknown -): nodeValue is { image_url: string } { - if (typeof nodeValue !== "object" || !nodeValue) { - return false; - } - - return "image_url" in nodeValue; -} diff --git a/packages/board-server/src/app/utils/input.ts b/packages/board-server/src/app/utils/input.ts deleted file mode 100644 index 952ca115566..00000000000 --- a/packages/board-server/src/app/utils/input.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { Schema } from "@google-labs/breadboard"; - -export function isMultiline(schema: Schema) { - return ( - schema.format === "multiline" || - schema.type === "object" || - schema.type === "array" - ); -} - -export function isSelect(schema: Schema) { - return schema.enum && schema.enum.length > 0; -} - -export function isBoolean(schema: Schema) { - return schema.type == "boolean"; -} diff --git a/packages/board-server/src/app/utils/kit-loader.ts b/packages/board-server/src/app/utils/kit-loader.ts deleted file mode 100644 index 94144f4eb84..00000000000 --- a/packages/board-server/src/app/utils/kit-loader.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - type KitConstructor, - type Kit, - asRuntimeKit, -} from "@google-labs/breadboard"; - -export const loadKits = async (kiConstructors: KitConstructor[]) => { - return kiConstructors.map((kitConstructor) => asRuntimeKit(kitConstructor)); -}; diff --git a/packages/board-server/src/app/utils/llm-content.ts b/packages/board-server/src/app/utils/llm-content.ts deleted file mode 100644 index 1ec21fd175c..00000000000 --- a/packages/board-server/src/app/utils/llm-content.ts +++ /dev/null @@ -1,134 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { type Schema } from "@google-labs/breadboard"; -import { type AllowedLLMContentTypes } from "../types/types.js"; - -function updateAllowList( - allow: AllowedLLMContentTypes, - format: string | string[] -) { - if (typeof format === "string") { - switch (format) { - case "audio-file": { - allow.audioFile = true; - break; - } - - case "audio-microphone": { - allow.audioMicrophone = true; - break; - } - - case "video-file": { - allow.videoFile = true; - break; - } - - case "video-webcam": { - allow.videoWebcam = true; - break; - } - - case "image-file": { - allow.imageFile = true; - break; - } - - case "image-webcam": { - allow.imageWebcam = true; - break; - } - - case "image-drawable": { - allow.imageDrawable = true; - break; - } - - case "text-file": { - allow.textFile = true; - break; - } - } - } else { - for (const item of format) { - updateAllowList(allow, item); - } - } -} - -export function getMinItemsFromProperty(property: Schema | undefined): number { - if (!property) { - return 0; - } - - if (property.minItems) { - return property.minItems; - } - - if ( - property.items && - !Array.isArray(property.items) && - property.items.minItems !== undefined - ) { - return property.items.minItems; - } - - return 0; -} - -export function createAllowListFromProperty( - property: Schema | undefined -): AllowedLLMContentTypes { - const allow: AllowedLLMContentTypes = { - audioFile: false, - audioMicrophone: false, - videoFile: false, - videoWebcam: false, - imageFile: false, - imageWebcam: false, - imageDrawable: false, - textFile: false, - textInline: true, - }; - - if (!property) { - return allow; - } - - let format = property.format; - if ( - property.type === "array" && - property.type && - property.items && - property.type === "array" && - !Array.isArray(property.items) && - property.items.type === "object" && - property.items.format - ) { - format = property.items.format; - } - - if (format) { - if (format.includes(",")) { - updateAllowList(allow, format.split(",")); - } else { - updateAllowList(allow, format); - } - } else { - allow.audioFile = true; - allow.audioMicrophone = true; - allow.videoFile = true; - allow.videoWebcam = true; - allow.imageFile = true; - allow.imageWebcam = true; - allow.imageDrawable = true; - allow.textFile = true; - allow.textInline = true; - } - - return allow; -} diff --git a/packages/board-server/src/app/utils/settings-helper.ts b/packages/board-server/src/app/utils/settings-helper.ts deleted file mode 100644 index 6f582043ed5..00000000000 --- a/packages/board-server/src/app/utils/settings-helper.ts +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as BreadboardUI from "@breadboard-ai/shared-ui"; - -const SETTINGS_KEY = "app-settings"; - -type Settings = { - [section: string]: { - [name: string]: BreadboardUI.Types.SettingEntry["value"]; - }; -}; - -export class AppSettingsHelper implements BreadboardUI.Types.SettingsHelper { - get( - section: BreadboardUI.Types.SETTINGS_TYPE, - name: string - ): BreadboardUI.Types.SettingEntry["value"] | undefined { - const settings = localStorage.getItem(SETTINGS_KEY); - if (!settings) { - return undefined; - } - const parsedSettings = JSON.parse(settings); - return parsedSettings[section]?.[name]; - } - async set( - section: BreadboardUI.Types.SETTINGS_TYPE, - name: string, - value: BreadboardUI.Types.SettingEntry["value"] - ): Promise { - const settings = localStorage.getItem(SETTINGS_KEY); - let parsedSettings: Settings = {}; - if (settings) { - parsedSettings = JSON.parse(settings); - } - if (!parsedSettings[section]) { - parsedSettings[section] = {}; - } - parsedSettings[section][name] = value; - localStorage.setItem(SETTINGS_KEY, JSON.stringify(parsedSettings)); - } - async delete( - section: BreadboardUI.Types.SETTINGS_TYPE, - name: string - ): Promise { - const settings = localStorage.getItem(SETTINGS_KEY); - if (!settings) { - return; - } - const parsedSettings = JSON.parse(settings); - if (!parsedSettings[section]) { - return; - } - delete parsedSettings[section][name]; - localStorage.setItem(SETTINGS_KEY, JSON.stringify(parsedSettings)); - } -} diff --git a/packages/board-server/src/app/utils/types.ts b/packages/board-server/src/app/utils/types.ts deleted file mode 100644 index 190b6ac4616..00000000000 --- a/packages/board-server/src/app/utils/types.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { TypedEventTarget } from "@google-labs/breadboard"; - -export type InviteListResponse = - | { success: true; invites: string[] } - | { success: false; error: string }; - -export type CreateInviteResponse = - | { success: true; invite: string } - | { success: false; error: string }; - -export type DeleteInviteResponse = - | { success: true; deleted: string } - | { success: false; error: string }; - -export enum VisitorState { - /** - * The user state is not yet known. - */ - LOADING, - /** - * The user is not signed in and has no active invite. - * Can't run boards on the board server, can't manage invites. - * Can update the board server key, which may change the state. - */ - VISITOR, - /** - * The user accepted invite. - * Can run boards on the board server. - * Can't manage invites. - * Can add the board server key, which may change the state. - */ - INVITEE, - /** - * The user is signed in or invite is active. - * Can run boards on the board server, but can't manage invites. - * Can update the board server key, which may change the state. - */ - USER, - /** - * The user is signed in and is the owner of the board. Can do everything - * that the "user" can do, plus manage invites. - */ - OWNER, -} - -export type VisitorStateChangeEvent = Event & { - state: VisitorState; - previous: VisitorState; -}; - -export type VisitorStateEventMap = { - change: VisitorStateChangeEvent; -}; - -export type VisitorStateEventTarget = TypedEventTarget; diff --git a/packages/board-server/src/app/utils/visitor-state-manager.ts b/packages/board-server/src/app/utils/visitor-state-manager.ts deleted file mode 100644 index 56175aa58a3..00000000000 --- a/packages/board-server/src/app/utils/visitor-state-manager.ts +++ /dev/null @@ -1,277 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createContext } from "@lit/context"; -import { - VisitorState, - type CreateInviteResponse, - type DeleteInviteResponse, - type InviteListResponse, - type VisitorStateChangeEvent, - type VisitorStateEventTarget, -} from "./types.js"; - -const GUEST_KEY_PREFIX = "bb-guest-key-"; -const BOARD_SERVER_KEY = "board-server-key"; - -const toBoardInfo = (url: URL) => { - const path = url.pathname.slice(1); - const [, userStore, boardName] = path.split("/"); - if (!userStore || userStore[0] !== "@") { - return {}; - } - return { userStore: userStore.slice(1), boardName }; -}; - -export const toGuestKey = (url: URL) => { - const { userStore, boardName } = toBoardInfo(url); - if (!userStore || !boardName) { - return undefined; - } - return `${GUEST_KEY_PREFIX}${userStore}/${boardName}`; -}; - -export const visitorStateManagerContext = createContext( - "visitorStateManager" -); - -export const getGuestKey = () => { - const url = new URL(window.location.href); - const guestStorageKey = toGuestKey(url); - if (guestStorageKey) { - return globalThis.localStorage.getItem(guestStorageKey); - } - return null; -}; - -const opts = { - composed: true, - bubbles: false, - cancelable: true, -}; - -class ChangeEvent extends Event implements VisitorStateChangeEvent { - static readonly eventName = "change"; - - constructor( - public state: VisitorState, - public previous: VisitorState - ) { - super(ChangeEvent.eventName, { ...opts }); - } -} - -export class VisitorStateManager extends (EventTarget as VisitorStateEventTarget) { - #url: string | null; - #inviteList: string[] | null = null; - #pending = false; - #visitorState: VisitorState = VisitorState.LOADING; - /** - * The API key for the board server. If this is set, the user is at least a - * "user". - */ - #boardServerApiKey: string | null = null; - /** - * The invite key for the guest. If this is set, the user is an - * "invitee". Both this and #boardServerApiKey can not be set at the - * same time. - */ - #guestKey: string | null = null; - - constructor() { - super(); - this.#boardServerApiKey = localStorage.getItem(BOARD_SERVER_KEY); - if (!this.#boardServerApiKey) { - this.#guestKey = getGuestKey(); - this.#url = null; - } else { - this.#url = this.#createInviteManagementApiUrl(); - } - } - - #createInviteManagementApiUrl() { - const url = new URL(window.location.href); - url.search = ""; - const inviteURL = new URL(url.href.replace(/app$/, "invite")); - inviteURL.searchParams.set("API_KEY", this.#boardServerApiKey!); - return inviteURL.href; - } - - boardServerKey(): string | null { - return this.#boardServerApiKey || this.#guestKey; - } - - #checkForInvite() { - const url = new URL(window.location.href); - const invite = url.searchParams.get("invite"); - if (!invite) { - return; - } - - const guestStorageKey = toGuestKey(url); - if (!guestStorageKey) { - // This is not a valid board URL. Something has gone wrong, let's bail. - return; - } - - // update the URL to remove the invite without changing history - url.searchParams.delete("invite"); - history.replaceState(null, "", url.toString()); - - // store the invite in local storage - globalThis.localStorage.setItem(guestStorageKey, invite); - this.#guestKey = invite; - } - - async #updateVisitorState() { - const previousState = this.#visitorState; - if (!this.#boardServerApiKey) { - this.#visitorState = this.#guestKey - ? VisitorState.INVITEE - : VisitorState.VISITOR; - } else { - this.#visitorState = VisitorState.LOADING; - const canCreate = await this.canCreateInvite(); - this.#visitorState = canCreate ? VisitorState.OWNER : VisitorState.USER; - } - if (previousState === this.#visitorState) { - return; - } - this.dispatchEvent(new ChangeEvent(this.#visitorState, previousState)); - } - - async init(): Promise { - this.#checkForInvite(); - await this.#updateVisitorState(); - } - - expireInvite() { - const guestStorageKey = toGuestKey(new URL(window.location.href)); - if (!guestStorageKey) { - return; - } - - globalThis.localStorage.removeItem(guestStorageKey); - this.#guestKey = null; - this.#updateVisitorState(); - } - - boardServerApiKey(): string | null { - return this.#boardServerApiKey; - } - - setBoardServerApiKey(key: string) { - if (key === "") { - this.#boardServerApiKey = null; - this.#guestKey = getGuestKey(); - this.#url = null; - globalThis.localStorage.removeItem(BOARD_SERVER_KEY); - } else { - this.#boardServerApiKey = key; - this.#url = this.#createInviteManagementApiUrl(); - this.#guestKey = null; - globalThis.localStorage.setItem(BOARD_SERVER_KEY, key); - } - this.#updateVisitorState(); - } - - visitorState(): VisitorState { - return this.#visitorState; - } - - url(): string | null { - return this.#url; - } - - inviteUrl(invite: string): string { - const inviteURL = new URL(window.location.href); - // Just in case. - inviteURL.searchParams.delete("API_KEY"); - inviteURL.searchParams.set("invite", invite); - return inviteURL.href; - } - - async listInvites(): Promise { - if (!this.#url) { - return { success: false, error: "No board server key" }; - } - if (this.#pending) { - return { success: false, error: "Request already pending" }; - } - if (this.#inviteList !== null) { - return { success: true, invites: this.#inviteList }; - } - this.#pending = true; - try { - const result = await fetch(this.#url, { credentials: "include" }); - const json = await result.json(); - if ("error" in json) { - return { success: false, error: json.error }; - } - this.#inviteList = json.invites; - this.#pending = false; - return { success: true, ...json }; - } catch (e) { - this.#pending = false; - return { success: false, error: (e as Error).message }; - } - } - - async canCreateInvite(): Promise { - const result = await this.listInvites(); - return result.success; - } - - async createInvite(): Promise { - if (!this.#url) { - return { success: false, error: "No board server key" }; - } - try { - const response = await fetch(this.#url, { - method: "POST", - credentials: "include", - }); - const result = await response.json(); - this.#inviteList = null; - return { success: true, invite: result.invite }; - } catch (e) { - return { success: false, error: (e as Error).message }; - } - } - - /** - * Same as createInvite, but if an invite already exists, it will return that - * instead of creating a new one. - */ - async getOrCreateInvite(): Promise { - const invites = await this.listInvites(); - if (invites.success && invites.invites.length > 0) { - return { success: true, invite: invites.invites[0] as string }; - } - return this.createInvite(); - } - - async deleteInvite(invite: string): Promise { - if (!this.#url) { - return { success: false, error: "No board server key" }; - } - try { - const response = await fetch(this.#url, { - method: "POST", - credentials: "include", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ delete: invite }), - }); - const result = await response.json(); - this.#inviteList = null; - return result; - } catch (e) { - return { success: false, error: (e as Error).message }; - } - } -} diff --git a/packages/board-server/src/app/utils/vite-env.d.ts b/packages/board-server/src/app/utils/vite-env.d.ts deleted file mode 100644 index 11f02fe2a00..00000000000 --- a/packages/board-server/src/app/utils/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/packages/board-server/src/index.ts b/packages/board-server/src/index.ts deleted file mode 100644 index e3744fbb236..00000000000 --- a/packages/board-server/src/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { startServer } from "./server.js"; - -// Start the server -(async () => { - try { - await startServer(); - } catch (err) { - console.error("Failed to start the server", err); - process.exit(1); // Exit with a failure code - } -})(); diff --git a/packages/board-server/src/router.ts b/packages/board-server/src/router.ts deleted file mode 100644 index 26f9c5f4493..00000000000 --- a/packages/board-server/src/router.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { IncomingMessage, ServerResponse } from "node:http"; - -import { serveBoardsAPI } from "./server/boards/index.js"; -import { serveContent } from "./server/common.js"; -import type { ServerConfig } from "./server/config.js"; -import { serveHome } from "./server/home/index.js"; -import { serveInfoAPI } from "./server/info/index.js"; -import { serveProxyAPI } from "./server/proxy/index.js"; -import { serverError } from "./server/errors.js"; - -const handleError = (err: Error, res: ServerResponse) => { - console.error("Server Error:", err); - if (!res.writableEnded) { - serverError(res, "Internal server error"); - } -}; - -export function makeRouter(serverConfig: ServerConfig) { - return async function router( - req: IncomingMessage, - res: ServerResponse - ): Promise { - try { - if (await serveHome(req, res)) { - return; - } - - if (await serveProxyAPI(serverConfig, req, res)) { - return; - } - - if (await serveInfoAPI(req, res)) { - return; - } - - if (await serveBoardsAPI(serverConfig, req, res)) { - return; - } - - serveContent(serverConfig, req, res); - } catch (err) { - handleError(err as Error, res); - } - }; -} diff --git a/packages/board-server/src/server.ts b/packages/board-server/src/server.ts deleted file mode 100644 index 04998b212df..00000000000 --- a/packages/board-server/src/server.ts +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createServer } from "http"; -import { createServer as createViteServer } from "vite"; -import { env } from "process"; -import { makeRouter } from "./router.js"; -import type { ServerConfig } from "./server/config.js"; -import { dirname, resolve } from "path"; -import { fileURLToPath } from "url"; - -const MODULE_PATH = dirname(fileURLToPath(import.meta.url)); -const ROOT_PATH = resolve(MODULE_PATH, "../../"); - -export const startServer = async (rootPath: string = ROOT_PATH) => { - const PORT = env.PORT || 3000; - const HOST = env.HOST || "localhost"; - const HOSTNAME = `http://${HOST}:${PORT}`; - const IS_PROD = env.NODE_ENV === "production"; - - const serverConfig: ServerConfig = { - allowedOrigins: new Set( - (process.env["ALLOWED_ORIGINS"] ?? "") - .split(/\s+/) - .filter((origin) => origin !== "") - ), - hostname: HOSTNAME, - viteDevServer: IS_PROD - ? null - : await createViteServer({ - server: { middlewareMode: true }, - appType: "custom", - optimizeDeps: { esbuildOptions: { target: "esnext" } }, - }), - rootPath - }; - - const server = createServer(makeRouter(serverConfig)); - - return new Promise<{ server: any; port: string | number }>( - (resolve, reject) => { - server.listen(PORT, () => { - console.info(`Running on "${HOSTNAME}"...`); - resolve({ server, port: PORT }); - }); - - server.on("error", (error) => { - reject(error); - }); - } - ); -}; - -export const stopServer = (server: any) => { - return new Promise((resolve, reject) => { - server.close((err: Error | null) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); -}; diff --git a/packages/board-server/src/server/auth.ts b/packages/board-server/src/server/auth.ts deleted file mode 100644 index 96d8f221ae9..00000000000 --- a/packages/board-server/src/server/auth.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { IncomingMessage, ServerResponse } from "http"; - -/** - * For now, make a flag that controls whether to use simple requests or not. - * Simple requests use "API_KEY" query parameter for authentication. * - */ -const USE_SIMPLE_REQUESTS = true; - -export const getUserKey = (req: IncomingMessage) => { - if (USE_SIMPLE_REQUESTS) { - const url = new URL(req.url || "", "http://localhost"); - return url.searchParams.get("API_KEY"); - } - - const auth = req.headers.authorization; - if (!auth) { - return null; - } - - const [type, token] = auth.split(" "); - if (type !== "Bearer") { - return null; - } - return token || null; -}; - -export const authenticate = ( - req: IncomingMessage, - res: ServerResponse -): string | null => { - const userKey = getUserKey(req); - if (!userKey) { - res.writeHead(401, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ error: "Unauthorized" })); - return null; - } - return userKey; -}; diff --git a/packages/board-server/src/server/boards/create.ts b/packages/board-server/src/server/boards/create.ts deleted file mode 100644 index b635d21e5f9..00000000000 --- a/packages/board-server/src/server/boards/create.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { authenticate } from "../auth.js"; -import { getStore } from "../store.js"; -import type { ApiHandler } from "../types.js"; - -export type CreateRequest = { - name: string; - dryRun?: boolean; -}; - -const create: ApiHandler = async (_path, req, res) => { - const userKey = authenticate(req, res); - if (!userKey) { - return true; - } - const store = getStore(); - - const chunks: string[] = []; - - return new Promise((resolve) => { - req.on("data", (chunk) => { - chunks.push(chunk.toString()); - }); - - req.on("end", async () => { - const request = JSON.parse(chunks.join("")) as CreateRequest; - const name = request.name; - const result = await store.create(userKey, name, !!request.dryRun); - - if (!result.success) { - res.writeHead(400, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ error: result.error })); - resolve(false); - return; - } - - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ path: result.path })); - resolve(true); - }); - }); -}; - -export default create; diff --git a/packages/board-server/src/server/boards/delete.ts b/packages/board-server/src/server/boards/delete.ts deleted file mode 100644 index da141975fa0..00000000000 --- a/packages/board-server/src/server/boards/delete.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { authenticate } from "../auth.js"; -import { serverError } from "../errors.js"; -import { getStore } from "../store.js"; -import type { ApiHandler, BoardParseResult } from "../types.js"; - -const del: ApiHandler = async (parsed, req, res, body) => { - const { board: path } = parsed as BoardParseResult; - - const userKey = authenticate(req, res); - if (!userKey) { - return true; - } - - const store = getStore(); - const userStore = await store.getUserStore(userKey); - if (!userStore.success) { - serverError(res, "Unauthorized"); - return true; - } - - if (!body) { - serverError(res, "No body provided"); - return true; - } - - const maybeDelete = body as { delete: boolean }; - - if (maybeDelete.delete !== true) { - return false; - } - - const result = await store.delete(userStore.store, path); - if (!result.success) { - serverError(res, result.error!); - return true; - } - - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ deleted: path })); - return true; -}; - -export default del; diff --git a/packages/board-server/src/server/boards/describe.ts b/packages/board-server/src/server/boards/describe.ts deleted file mode 100644 index 2e418c298b7..00000000000 --- a/packages/board-server/src/server/boards/describe.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - createLoader, - inspect, - type GraphDescriptor, - type NodeDescriberResult, -} from "@google-labs/breadboard"; -import { serverError } from "../errors.js"; -import { asInfo, getStore } from "../store.js"; -import type { ApiHandler, BoardParseResult } from "../types.js"; - -export const addKeyInput = (describeResult: NodeDescriberResult) => { - const inputSchema = describeResult.inputSchema; - const properties = inputSchema.properties; - if (properties) { - properties.$key = { - type: "string", - title: "Service Key", - description: "The key to access the service", - }; - } - inputSchema.required ??= []; - inputSchema.required.push("$key"); -}; - -const describe: ApiHandler = async (parsed, _req, res) => { - const store = getStore(); - const { user, name } = parsed as BoardParseResult; - - const board = JSON.parse(await store.get(user!, name!)) as - | GraphDescriptor - | undefined; - if (!board) { - serverError(res, "Board not found"); - return true; - } - - const loader = createLoader(); - const inspector = inspect(board, { loader }); - const { title, description, metadata } = board; - const describeResult = await inspector.describe(); - addKeyInput(describeResult); - const result = { - ...describeResult, - title, - description, - metadata, - } as NodeDescriberResult; - - res.writeHead(200, { - "Content-Type": "application/json", - }); - res.end(JSON.stringify(result)); - - return true; -}; - -export default describe; diff --git a/packages/board-server/src/server/boards/get.ts b/packages/board-server/src/server/boards/get.ts deleted file mode 100644 index 2dea9a80232..00000000000 --- a/packages/board-server/src/server/boards/get.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { getStore } from "../store.js"; -import type { ApiHandler, BoardParseResult } from "../types.js"; - -const get: ApiHandler = async (parsed, req, res) => { - const { user, name } = parsed as BoardParseResult; - - const store = getStore(); - - const board = await store.get(user!, name!); - - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(board); - return true; -}; - -export default get; diff --git a/packages/board-server/src/server/boards/index.ts b/packages/board-server/src/server/boards/index.ts deleted file mode 100644 index ea6021b7629..00000000000 --- a/packages/board-server/src/server/boards/index.ts +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { IncomingMessage, ServerResponse } from "http"; -import type { ViteDevServer } from "vite"; - -import { methodNotAllowed } from "../errors.js"; -import { serveFile, serveIndex } from "../common.js"; -import type { ServerConfig } from "../config.js"; -import { cors, corsAll } from "../cors.js"; -import { getStore } from "../store.js"; -import type { BoardParseResult, PageMetadata } from "../types.js"; - -import list from "./list.js"; -import create from "./create.js"; -import get from "./get.js"; -import post from "./post.js"; -import del from "./delete.js"; -import invoke from "./invoke.js"; -import describe from "./describe.js"; -import inviteList from "./invite-list.js"; -import inviteUpdate from "./invite-update.js"; -import { parse } from "./utils/board-api-parser.js"; -import run from "./run.js"; - -const getBody = async (req: IncomingMessage): Promise => { - const chunks: string[] = []; - - return new Promise((resolve) => { - req.on("data", (chunk) => { - chunks.push(chunk.toString()); - }); - - req.on("end", () => { - const body = chunks.join(""); - if (!body) { - resolve(undefined); - } - try { - resolve(JSON.parse(body)); - } catch (e) { - resolve(undefined); - } - }); - }); -}; - -const getMetadata = (parsed: BoardParseResult) => { - const { user, name } = parsed; - return async (): Promise => { - const store = getStore(); - const board = await store.get(user!, name!); - try { - return JSON.parse(board) as PageMetadata; - } catch { - return null; - } - }; -}; - -export const serveBoardsAPI = async ( - serverConfig: ServerConfig, - req: IncomingMessage, - res: ServerResponse -): Promise => { - const url = new URL(req.url || "", serverConfig.hostname); - const parsed = parse(url, req.method); - - if (!parsed.success) { - if (parsed.code === 404) { - return false; - } - if (parsed.code === 405) { - methodNotAllowed(res, parsed.error); - return true; - } - return false; - } - - switch (parsed.type) { - case "list": { - if (!cors(req, res, serverConfig.allowedOrigins)) return true; - if (await list(parsed, req, res)) return true; - break; - } - case "create": { - if (!cors(req, res, serverConfig.allowedOrigins)) return true; - if (await create(parsed, req, res)) return true; - break; - } - case "get": { - if (!corsAll(req, res)) return true; - if (await get(parsed, req, res)) return true; - break; - } - case "update": { - if (!cors(req, res, serverConfig.allowedOrigins)) return true; - const body = await getBody(req); - if (await post(parsed, req, res, body)) return true; - if (await del(parsed, req, res, body)) return true; - break; - } - case "app": { - // Serve the index.html file for the app. - serveIndex(serverConfig, res, getMetadata(parsed)); - return true; - } - case "api": { - serveFile(serverConfig, res, "/api.html"); - return true; - } - case "invoke": { - if (!corsAll(req, res)) return true; - const body = await getBody(req); - if (await invoke(parsed, req, res, body)) return true; - break; - } - case "describe": { - if (!corsAll(req, res)) return true; - if (await describe(parsed, req, res)) return true; - break; - } - case "run": { - if (!corsAll(req, res)) return true; - const body = await getBody(req); - if (await run(parsed, req, res, body)) return true; - break; - } - case "invite-list": { - if (!cors(req, res, serverConfig.allowedOrigins)) return true; - if (await inviteList(parsed, req, res)) return true; - break; - } - case "invite-update": { - if (!cors(req, res, serverConfig.allowedOrigins)) return true; - const body = await getBody(req); - if (await inviteUpdate(parsed, req, res, body)) return true; - break; - } - default: { - return false; - } - } - return false; -}; diff --git a/packages/board-server/src/server/boards/invite-list.ts b/packages/board-server/src/server/boards/invite-list.ts deleted file mode 100644 index 0c27aa897b6..00000000000 --- a/packages/board-server/src/server/boards/invite-list.ts +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { authenticate } from "../auth.js"; -import { serverError, unauthorized } from "../errors.js"; -import { getStore } from "../store.js"; -import type { ApiHandler, BoardParseResult } from "../types.js"; - -const inviteList: ApiHandler = async (parsed, req, res) => { - const { board: path } = parsed as BoardParseResult; - - const userKey = authenticate(req, res); - if (!userKey) { - unauthorized(res, "Unauthorized"); - return true; - } - - const store = getStore(); - - const userStore = await store.getUserStore(userKey); - if (!userStore.success) { - unauthorized(res, "Unauthorized"); - return true; - } - - const result = await store.listInvites(userStore.store, path); - let responseBody; - if (!result.success) { - // TODO: Be nice and return a proper error code - responseBody = { error: result.error }; - } else { - responseBody = { invites: result.invites }; - } - - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(JSON.stringify(responseBody)); - return true; -}; - -export default inviteList; diff --git a/packages/board-server/src/server/boards/invite-update.ts b/packages/board-server/src/server/boards/invite-update.ts deleted file mode 100644 index a1ee3bf84a6..00000000000 --- a/packages/board-server/src/server/boards/invite-update.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { authenticate } from "../auth.js"; -import { serverError, unauthorized } from "../errors.js"; -import { getStore } from "../store.js"; -import type { ApiHandler, BoardParseResult } from "../types.js"; - -const updateInvite: ApiHandler = async (parsed, req, res, body) => { - const { board: path } = parsed as BoardParseResult; - - const userKey = authenticate(req, res); - if (!userKey) { - unauthorized(res, "Unauthorized"); - return true; - } - const store = getStore(); - const userStore = await store.getUserStore(userKey); - if (!userStore.success) { - unauthorized(res, "Unauthorized"); - return true; - } - - if (!body) { - // create new invite - const result = await store.createInvite(userStore.store, path); - let responseBody; - if (!result.success) { - responseBody = { error: result.error }; - } else { - responseBody = { invite: result.invite }; - } - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(JSON.stringify(responseBody)); - return true; - } else { - // delete invite - const del = body as { delete: string }; - if (!del.delete) { - return false; - } - const result = await store.deleteInvite(userStore.store, path, del.delete); - let responseBody; - if (!result.success) { - // TODO: Be nice and return a proper error code - responseBody = { error: result.error }; - } else { - responseBody = { deleted: del.delete }; - } - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(JSON.stringify(responseBody)); - return true; - } -}; - -export default updateInvite; diff --git a/packages/board-server/src/server/boards/invoke.ts b/packages/board-server/src/server/boards/invoke.ts deleted file mode 100644 index 291cdebef0a..00000000000 --- a/packages/board-server/src/server/boards/invoke.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { ApiHandler, BoardParseResult } from "../types.js"; -import { loadFromStore } from "./utils/board-server-provider.js"; -import { verifyKey } from "./utils/verify-key.js"; -import { secretsKit } from "../proxy/secrets.js"; -import { invokeBoard } from "./utils/invoke-board.js"; - -const invokeHandler: ApiHandler = async (parsed, req, res, body) => { - const { board, url, name, user } = parsed as BoardParseResult; - const inputs = body as Record; - const keyVerificationResult = await verifyKey(user, name, inputs); - if (!keyVerificationResult.success) { - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ $error: keyVerificationResult.error })); - return true; - } - const result = await invokeBoard({ - url, - path: board, - inputs, - loader: loadFromStore, - kitOverrides: [secretsKit], - }); - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(JSON.stringify(result)); - return true; -}; - -export default invokeHandler; diff --git a/packages/board-server/src/server/boards/list.ts b/packages/board-server/src/server/boards/list.ts deleted file mode 100644 index 91836622d13..00000000000 --- a/packages/board-server/src/server/boards/list.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { getUserKey } from "../auth.js"; -import { getStore } from "../store.js"; -import type { ApiHandler } from "../types.js"; - -const list: ApiHandler = async (_path, req, res) => { - const store = getStore(); - const userKey = getUserKey(req); - const boards = await store.list(userKey); - - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(JSON.stringify(boards)); - return true; -}; - -export default list; diff --git a/packages/board-server/src/server/boards/post.ts b/packages/board-server/src/server/boards/post.ts deleted file mode 100644 index 279fb77aff8..00000000000 --- a/packages/board-server/src/server/boards/post.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { GraphDescriptor } from "@google-labs/breadboard"; -import { authenticate } from "../auth.js"; -import { serverError } from "../errors.js"; -import { getStore } from "../store.js"; -import type { ApiHandler, BoardParseResult } from "../types.js"; - -const post: ApiHandler = async (parsed, req, res, body) => { - const { board: path } = parsed as BoardParseResult; - - const userKey = authenticate(req, res); - if (!userKey) { - serverError(res, "Unauthorized"); - return true; - } - const store = getStore(); - const userStore = await store.getUserStore(userKey); - - if (!userStore.success) { - serverError(res, "Unauthorized"); - return true; - } - - if (!body) { - serverError(res, "No body provided"); - return true; - } - - const maybeGraph = body as GraphDescriptor; - - if (!("nodes" in maybeGraph && "edges" in maybeGraph)) { - return false; - } - - const result = await store.update(userStore.store!, path, maybeGraph); - if (!result.success) { - serverError(res, result.error); - return true; - } - - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ created: path })); - return true; -}; - -export default post; diff --git a/packages/board-server/src/server/boards/run.ts b/packages/board-server/src/server/boards/run.ts deleted file mode 100644 index c878b9a0721..00000000000 --- a/packages/board-server/src/server/boards/run.ts +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { ApiHandler, BoardParseResult } from "../types.js"; -import { loadFromStore } from "./utils/board-server-provider.js"; -import { verifyKey } from "./utils/verify-key.js"; -import { secretsKit } from "../proxy/secrets.js"; -import { runBoard, timestamp } from "./utils/run-board.js"; -import { getStore } from "../store.js"; -import type { RemoteMessage } from "@google-labs/breadboard/remote"; - -const runHandler: ApiHandler = async (parsed, req, res, body) => { - const { board, url, name, user } = parsed as BoardParseResult; - const { - $next: next, - $diagnostics: diagnostics, - ...inputs - } = body as Record; - const writer = new WritableStream({ - write(chunk) { - res.write(`data: ${JSON.stringify(chunk)}\n\n`); - }, - }).getWriter(); - res.setHeader("Content-Type", "text/event-stream"); - res.statusCode = 200; - - const keyVerificationResult = await verifyKey(user, name, inputs); - if (!keyVerificationResult.success) { - await writer.write([ - "graphstart", - { - path: [], - timestamp: timestamp(), - graph: { nodes: [], edges: [] }, - }, - ]); - await writer.write([ - "error", - { error: "Invalid or missing key", code: 403, timestamp: timestamp() }, - ]); - await writer.write([ - "graphend", - { - path: [], - timestamp: timestamp(), - }, - ]); - await writer.close(); - res.end(); - return true; - } - - const runStateStore = getStore(); - - await runBoard({ - url, - path: board, - user: keyVerificationResult.user!, - inputs, - loader: loadFromStore, - kitOverrides: [secretsKit], - writer, - next, - runStateStore, - diagnostics, - }); - // await writer.close(); - res.end(); - return true; -}; - -export default runHandler; diff --git a/packages/board-server/src/server/boards/utils/board-api-parser.ts b/packages/board-server/src/server/boards/utils/board-api-parser.ts deleted file mode 100644 index 763989a898b..00000000000 --- a/packages/board-server/src/server/boards/utils/board-api-parser.ts +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { IncomingMessage } from "http"; -import type { ParseResult } from "../../types.js"; - -const API_ENTRY = "/boards"; - -export const parseBoardURL = (url: URL, req: IncomingMessage): string => { - const { pathname } = url; - - return url.pathname; -}; - -const notFound = (): ParseResult => ({ - success: false, - error: "Not found", - code: 404, -}); - -const invalidMethod = (): ParseResult => ({ - success: false, - error: "Invalid method", - code: 405, -}); - -export const parse = (url: URL, method: string = "GET"): ParseResult => { - const parser = new BoardAPIParser(url, method); - return parser.parse(); -}; - -/** - * Boards API routing logic: - * GET /boards/ -> list boards - * POST /boards/ -> create a new board - * GET /boards/@:user/:name.json -> get a board - * POST /boards/@:user/:name.json -> update/delete a board - * GET /boards/@:user/:name.app -> serve frontend app for the board - * GET /boards/@:user/:name.api -> serve API description for the board - * POST /boards/@:user/:name.api/invoke -> BSE invoke entry point - * POST /boards/@:user/:name.api/describe -> BSE describe entry point - * POST /boards/@:user/:name.api/run -> Remote run entry point - * GET /boards/@:user/:name.invite -> Get list of current invites for the board - * POST /boards/@:user/:name.invite -> Create a new or delete existing invite - */ -export class BoardAPIParser { - #url: URL; - #method: string; - - constructor(url: URL, method: string) { - this.#url = url; - this.#method = method; - } - - isBoardURL(): boolean { - return this.#url.pathname.startsWith(API_ENTRY); - } - - #getAdjustedBoardURL = (board: string): string => { - const url = new URL(this.#url); - url.pathname = `${API_ENTRY}/${board}`; - url.search = ""; - return url.href; - }; - - parse(): ParseResult { - if (!this.isBoardURL()) { - return notFound(); - } - const isGET = this.#method === "GET"; - const isPOST = this.#method === "POST"; - const { pathname } = this.#url; - const parts = pathname.split("/").slice(2); - if (parts.length === 0) { - if (isGET) { - return { success: true, type: "list" }; - } else if (isPOST) { - return { success: true, type: "create" }; - } - return invalidMethod(); - } else if (parts.length === 1) { - return notFound(); - } else if (parts.length === 2 || parts.length === 3) { - const [maybeUser, maybeName] = parts; - const user = maybeUser?.startsWith("@") ? maybeUser.slice(1) : undefined; - if (!user || !maybeName) { - return notFound(); - } - const isAPI = maybeName.endsWith(".api"); - const isApp = maybeName.endsWith(".app"); - const isJson = maybeName.endsWith(".json"); - const isInvite = maybeName.endsWith(".invite"); - - if (isAPI) { - const isInvoke = parts.length === 3 && parts[2] === "invoke"; - const isDescribe = parts.length === 3 && parts[2] === "describe"; - const isRun = parts.length === 3 && parts[2] === "run"; - const name = `${maybeName.slice(0, -".api".length)}.json`; - const board = `@${user}/${name}`; - const url = this.#getAdjustedBoardURL(board); - if (isInvoke) { - if (isPOST) { - return { success: true, type: "invoke", board, url, user, name }; - } else { - return invalidMethod(); - } - } - if (isDescribe) { - if (isPOST) { - return { success: true, type: "describe", board, url, user, name }; - } else { - return invalidMethod(); - } - } - if (isRun) { - if (isPOST) { - return { success: true, type: "run", board, url, user, name }; - } else { - return invalidMethod(); - } - } - return { success: true, type: "api", board, url, user, name }; - } else if (isApp && parts.length === 2) { - const name = `${maybeName.slice(0, -".app".length)}.json`; - const board = `@${user}/${name}`; - const url = this.#getAdjustedBoardURL(board); - return { success: true, type: "app", board, url, user, name }; - } else if (isJson && parts.length === 2) { - const name = maybeName; - const board = `@${user}/${name}`; - const url = this.#getAdjustedBoardURL(board); - if (this.#method === "GET") { - return { success: true, type: "get", board, url, user, name }; - } else if (this.#method === "POST") { - return { success: true, type: "update", board, url, user, name }; - } - } else if (isInvite && parts.length === 2) { - const name = `${maybeName.slice(0, -".invite".length)}.json`; - const board = `@${user}/${name}`; - const url = this.#getAdjustedBoardURL(board); - if (this.#method === "GET") { - return { success: true, type: "invite-list", board, url, user, name }; - } else if (this.#method === "POST") { - return { - success: true, - type: "invite-update", - board, - url, - user, - name, - }; - } - } - } - return notFound(); - } -} diff --git a/packages/board-server/src/server/boards/utils/board-server-provider.ts b/packages/board-server/src/server/boards/utils/board-server-provider.ts deleted file mode 100644 index 21e071fbbb9..00000000000 --- a/packages/board-server/src/server/boards/utils/board-server-provider.ts +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - type ChangeNotificationCallback, - type GraphDescriptor, - type GraphProvider, - type GraphProviderCapabilities, - type GraphProviderExtendedCapabilities, - type GraphProviderStore, -} from "@google-labs/breadboard"; - -import { asInfo, getStore } from "../../store.js"; -import type { BoardServerLoadFunction } from "../../types.js"; - -export const loadFromStore = async ( - path: string -): Promise => { - const store = getStore(); - const { userStore, boardName } = asInfo(path); - if (!userStore || !boardName) { - return null; - } - const graph = JSON.parse(await store.get(userStore, boardName)); - return graph as GraphDescriptor; -}; - -export class BoardServerProvider implements GraphProvider { - #path: string; - #loader: BoardServerLoadFunction; - - name = "Board Server Provider"; - - constructor(path: string, loader: BoardServerLoadFunction) { - this.#path = path; - this.#loader = loader; - } - - async ready(): Promise { - return; - } - - isSupported(): boolean { - return true; - } - - canProvide(url: URL): false | GraphProviderCapabilities { - return url.href.endsWith(this.#path) - ? { - load: true, - save: false, - delete: false, - } - : false; - } - - extendedCapabilities(): GraphProviderExtendedCapabilities { - return { - modify: false, - connect: false, - disconnect: false, - refresh: false, - watch: false, - preview: false, - }; - } - - async load(_url: URL): Promise { - return this.#loader(this.#path); - } - - async save( - url: URL, - graph: GraphDescriptor - ): Promise<{ result: boolean; error?: string }> { - throw new Error("Method not supported."); - } - - createBlank(url: URL): Promise<{ result: boolean; error?: string }> { - throw new Error("Method not supported."); - } - - create( - url: URL, - graph: GraphDescriptor - ): Promise<{ result: boolean; error?: string }> { - throw new Error("Method not supported."); - } - - delete(url: URL): Promise<{ result: boolean; error?: string }> { - throw new Error("Method not supported."); - } - - connect: (location?: string, auth?: unknown) => Promise = - async () => { - throw new Error("Method not supported."); - }; - - disconnect: (location: string) => Promise = async () => { - throw new Error("Method not supported."); - }; - - refresh: (location: string) => Promise = async () => { - throw new Error("Method not supported."); - }; - - createURL: (location: string, fileName: string) => Promise = - async () => { - throw new Error("Method not supported."); - }; - - watch: (callback: ChangeNotificationCallback) => void = async () => { - throw new Error("Method not supported."); - }; - - parseURL(url: URL): { location: string; fileName: string } { - throw new Error("Method not supported."); - } - - restore: () => Promise = async () => { - throw new Error("Method not supported."); - }; - - items: () => Map = () => { - throw new Error("Method not supported."); - }; - - startingURL: () => URL | null = () => { - throw new Error("Method not supported."); - }; - - preview: (_url: URL) => Promise = () => { - throw new Error("Method not supported."); - }; -} diff --git a/packages/board-server/src/server/boards/utils/create-kits.ts b/packages/board-server/src/server/boards/utils/create-kits.ts deleted file mode 100644 index 600bd4c3a93..00000000000 --- a/packages/board-server/src/server/boards/utils/create-kits.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import AgentKit from "@google-labs/agent-kit/agent.kit.json" with { type: "json" }; -import { - asRuntimeKit, - type Kit, - type KitManifest, -} from "@google-labs/breadboard"; -import { fromManifest } from "@google-labs/breadboard/kits"; -import Core from "@google-labs/core-kit"; -import GeminiKit from "@google-labs/gemini-kit"; -import JSONKit from "@google-labs/json-kit"; -import TemplateKit from "@google-labs/template-kit"; - -export const createKits = (overrides: Kit[] = []) => [ - ...overrides, - asRuntimeKit(Core), - asRuntimeKit(JSONKit), - asRuntimeKit(TemplateKit), - asRuntimeKit(GeminiKit), - fromManifest(AgentKit as KitManifest), -]; diff --git a/packages/board-server/src/server/boards/utils/format-run-error.ts b/packages/board-server/src/server/boards/utils/format-run-error.ts deleted file mode 100644 index d0ddb8b8076..00000000000 --- a/packages/board-server/src/server/boards/utils/format-run-error.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export const formatRunError = (e: unknown) => { - if (typeof e === "string") { - return e; - } - if (e instanceof Error) { - return e.message; - } - if ("message" in (e as any)) { - return (e as { message: string }).message; - } - // Presume it's an ErrorObject. - const error = (e as { error: unknown }).error; - if (typeof error === "string") { - return error; - } - if (error instanceof Error) { - return error.message; - } - return JSON.stringify(error); -}; diff --git a/packages/board-server/src/server/boards/utils/invoke-board.ts b/packages/board-server/src/server/boards/utils/invoke-board.ts deleted file mode 100644 index e187eecc88d..00000000000 --- a/packages/board-server/src/server/boards/utils/invoke-board.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { getDataStore } from "@breadboard-ai/data-store"; -import { run, type HarnessRunResult } from "@google-labs/breadboard/harness"; -import { createKits } from "./create-kits.js"; -import { createLoader, inflateData } from "@google-labs/breadboard"; -import { BoardServerProvider } from "./board-server-provider.js"; -import { formatRunError } from "./format-run-error.js"; -import type { InvokeBoardArguments } from "../../types.js"; - -export const invokeBoard = async ({ - url, - path, - inputs, - loader, - kitOverrides, -}: InvokeBoardArguments) => { - const store = getDataStore(); - if (!store) { - return; - } - // TODO: Figure out if this is the right thing to do here. - store.createGroup("run-board"); - - const runner = run({ - url, - kits: createKits(kitOverrides), - loader: createLoader([new BoardServerProvider(path, loader)]), - store, - inputs: { model: "gemini-1.5-flash-latest" }, - interactiveSecrets: false, - }); - - for await (const result of runner) { - const { type, data, reply } = result as HarnessRunResult; - if (type === "input") { - await reply({ inputs }); - } else if (type === "output") { - return inflateData(store, data.outputs); - } else if (type === "error") { - return { - $error: formatRunError(data.error), - }; - } else if (type === "end") { - return { - $error: "Run completed without producing output.", - }; - } else { - console.log("UNKNOWN RESULT", type, data); - } - } - return { - $error: "Run completed without signaling end or error.", - }; -}; diff --git a/packages/board-server/src/server/boards/utils/run-board.ts b/packages/board-server/src/server/boards/utils/run-board.ts deleted file mode 100644 index 506bf4f2f8d..00000000000 --- a/packages/board-server/src/server/boards/utils/run-board.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { getDataStore } from "@breadboard-ai/data-store"; -import { createLoader, type ReanimationState } from "@google-labs/breadboard"; -import { handleRunGraphRequest } from "@google-labs/breadboard/remote"; -import type { RunBoardArguments } from "../../types.js"; -import { BoardServerProvider } from "./board-server-provider.js"; -import { createKits } from "./create-kits.js"; - -export const timestamp = () => globalThis.performance.now(); - -export const runBoard = async ({ - url, - path, - user, - inputs, - loader, - kitOverrides, - next, - writer, - runStateStore, - diagnostics = false, -}: RunBoardArguments): Promise => { - const store = getDataStore(); - if (!store) { - await writer.write([ - "error", - { error: "Data store not available.", timestamp: timestamp() }, - ]); - return; - } - // TODO: Figure out if this is the right thing to do here. - store.createGroup("run-board"); - - return handleRunGraphRequest( - { - inputs, - next, - diagnostics, - }, - { - url, - kits: createKits(kitOverrides), - writer, - loader: createLoader([new BoardServerProvider(path, loader)]), - dataStore: store, - stateStore: { - async load(next?: string) { - if (!next) { - return undefined; - } - return runStateStore.loadReanimationState(user, next); - }, - async save(state: ReanimationState) { - return runStateStore.saveReanimationState(user, state); - }, - }, - inputs: { model: "gemini-1.5-flash-latest" }, - diagnostics, - } - ); -}; diff --git a/packages/board-server/src/server/boards/utils/verify-key.ts b/packages/board-server/src/server/boards/utils/verify-key.ts deleted file mode 100644 index 4c95fecd587..00000000000 --- a/packages/board-server/src/server/boards/utils/verify-key.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { getStore } from "../../store.js"; - -export const verifyKey = async ( - user: string, - boardName: string, - inputs: Record | undefined -) => { - const key = inputs?.$key; - if (!key) { - return { success: false, error: "No key supplied" }; - } - delete inputs.$key; - const store = getStore(); - const userStore = await store.getUserStore(key); - if (userStore.success) { - return { success: true, user: userStore.store }; - } - const found = await store.findInvite(user, boardName, key); - if (found.success) { - return { success: true, user }; - } - return { success: false, error: found.error }; -}; diff --git a/packages/board-server/src/server/common.ts b/packages/board-server/src/server/common.ts deleted file mode 100644 index acbb922607a..00000000000 --- a/packages/board-server/src/server/common.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { readFile } from "fs/promises"; -import type { IncomingMessage, ServerResponse } from "http"; -import { extname } from "path"; - -import type { ServerConfig } from "./config.js"; -import { notFound } from "./errors.js"; -import type { PageMetadata } from "./types.js"; -import { createReadStream } from "fs"; - -const PROD_PATH = "/dist/client"; - -const CONTENT_TYPE = new Map([ - [".html", "text/html"], - [".json", "application/json"], - [".css", "text/css"], - [".js", "text/javascript"], - [".png", "image/png"], - [".svg", "image/svg+xml"], - [".ico", "image/x-icon"], - [".webp", "image/webp"], - [".woff", "font/woff"], - [".woff2", "font/woff2"], - [".ttf", "font/ttf"], - [".otf", "font/otf"], - [".eot", "application/vnd.ms-fontobject"], - [".mp3", "audio/mpeg"], - [".wav", "audio/wav"], - [".mp4", "video/mp4"], - [".webm", "video/webm"], - [".pdf", "application/pdf"], - [".md", "text/markdown"], - [".txt", "text/plain"], -]); -const DEFAULT_CONTENT_TYPE = "text/plain"; - -const IS_PROD = process.env.NODE_ENV === "production"; - -/** - * Serve a static file - */ -export const serveFile = async ( - serverConfig: ServerConfig, - res: ServerResponse, - path: string, - transformer?: (contents: string) => Promise -) => { - if (path == "/") { - path = "/index.html"; - } - if (IS_PROD) { - path = `${PROD_PATH}${path}`; - } - const contentType = CONTENT_TYPE.get(extname(path)) || DEFAULT_CONTENT_TYPE; - try { - const resolvedPath = `${serverConfig.rootPath}${path}`; - if (contentType.startsWith("text/") || contentType === "application/json") { - let contents = await readFile(resolvedPath, "utf-8"); - if (transformer) contents = await transformer(contents); - res.writeHead(200, { "Content-Type": contentType }); - res.end(contents); - } else { - return new Promise((resolve) => { - const fileStream = createReadStream(resolvedPath); - res.setHeader("Content-Type", contentType); - fileStream.pipe(res); - fileStream.on("error", () => { - notFound(res, `Static file not found`); - resolve(); - }); - fileStream.on("end", resolve); - }); - } - } catch { - notFound(res, "Static file not found"); - } -}; -export const serveContent = async ( - serverConfig: ServerConfig, - req: IncomingMessage, - res: ServerResponse -) => { - const pathname = expandImplicitIndex(req.url); - const vite = serverConfig.viteDevServer; - if (vite === null) { - serveFile(serverConfig, res, pathname); - } else { - if (pathname.endsWith(".html") && !req.url?.includes("?html-proxy")) { - serveFile(serverConfig, res, pathname, async (contents: string) => { - return await vite.transformIndexHtml(pathname, contents); - }); - return; - } - vite.middlewares(req, res); - } -}; - -function escapeHTML(s: string) { - return s - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, """) - .replace(/'/g, "'"); -} - -function replaceMetadata(contents: string, metadata: PageMetadata) { - return contents - .replaceAll("{{title}}", escapeHTML(metadata.title)) - .replaceAll("{{description}}", escapeHTML(metadata.description || "")); -} - -export const serveIndex = async ( - serverConfig: ServerConfig, - res: ServerResponse, - metadataGetter: () => Promise -) => { - const metadata = await metadataGetter(); - if (metadata === null) { - return notFound(res, "Board not found"); - } - const vite = serverConfig.viteDevServer; - if (vite === null) { - return serveFile( - serverConfig, - res, - "/index.html", - async (contents: string) => { - return replaceMetadata(contents, metadata); - } - ); - } - serveFile(serverConfig, res, "/", async (contents: string) => { - return await vite.transformIndexHtml( - "/index.html", - replaceMetadata(contents, metadata) - ); - }); -}; - -function expandImplicitIndex(urlString: string | undefined) { - if (!urlString) { - return "/"; - } - const url = new URL(urlString, "http://localhost"); - const path = url.pathname; - if (path.endsWith("/")) { - return `${path}index.html`; - } - return path; -} diff --git a/packages/board-server/src/server/config.ts b/packages/board-server/src/server/config.ts deleted file mode 100644 index b12b4eb4b4f..00000000000 --- a/packages/board-server/src/server/config.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { ViteDevServer } from "vite"; - -export interface ServerConfig { - allowedOrigins: Set; - hostname: string; - viteDevServer: ViteDevServer | null; - rootPath: string; -} diff --git a/packages/board-server/src/server/cors.ts b/packages/board-server/src/server/cors.ts deleted file mode 100644 index d77395dd8ab..00000000000 --- a/packages/board-server/src/server/cors.ts +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - IncomingMessage, - OutgoingHttpHeaders, - ServerResponse, -} from "http"; - -const CORS_HEADERS: OutgoingHttpHeaders = { - "Access-Control-Allow-Origin": "*", - "Access-Control-Allow-Methods": "OPTIONS, POST, GET, DELETE", - "Access-Control-Allow-Credentials": "true", - "Access-Control-Allow-Headers": - "Content-Type, Access-Control-Allow-Headers, Authorization", - "Access-Control-Max-Age": 2592000, // 30 days -}; - -export const corsAll = (req: IncomingMessage, res: ServerResponse) => { - const headers = { ...CORS_HEADERS }; - headers["Access-Control-Allow-Origin"] = req.headers.origin || "*"; - - if (req.method === "OPTIONS") { - res.writeHead(204, headers); - res.end(); - return false; - } - - const method = req.method || "GET"; - if (["GET", "POST"].indexOf(method) > -1) { - for (const [key, value] of Object.entries(headers)) { - if (value !== undefined) { - res.setHeader(key, value); - } - } - return true; - } - - res.writeHead(405); - res.end(`${req.method} is not allowed for the request.`); - return false; -}; - -export const cors = ( - req: IncomingMessage, - res: ServerResponse, - allowedOrigins: Set -) => { - const headers = { ...CORS_HEADERS }; - const origin = req.headers.origin || ""; - const host = req.headers.host || ""; - const sameOrigin = origin.includes(host); - - const isAllowed = - sameOrigin || origin.length === 0 || allowedOrigins.has(origin); - if (!isAllowed) { - res.writeHead(403); - res.end(`${origin} is not allowed for the request.`); - return false; - } - - headers["Access-Control-Allow-Origin"] = origin; - - if (req.method === "OPTIONS") { - res.writeHead(204, headers); - res.end(); - return false; - } - - const method = req.method || "GET"; - if (["GET", "POST"].indexOf(method) > -1) { - for (const [key, value] of Object.entries(headers)) { - if (value !== undefined) { - res.setHeader(key, value); - } - } - return true; - } - - res.writeHead(405); - res.end(`${req.method} is not allowed for the request.`); - return false; -}; diff --git a/packages/board-server/src/server/errors.ts b/packages/board-server/src/server/errors.ts deleted file mode 100644 index 0ad7dc1e619..00000000000 --- a/packages/board-server/src/server/errors.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { ServerResponse } from "http"; - -export const serverError = (res: ServerResponse, error: string) => { - res.writeHead(500, "Server Error"); - res.end(error); -}; - -export const methodNotAllowed = (res: ServerResponse, error: string) => { - res.writeHead(405, "Method Not Allowed"); - res.end(error); -}; - -export const notFound = (res: ServerResponse, error: string) => { - res.writeHead(404, "Page not found"); - res.end(error); -}; - -export const unauthorized = (res: ServerResponse, error: string) => { - res.writeHead(401, "Unauthorized"); - res.end(error); -}; diff --git a/packages/board-server/src/server/home/index.ts b/packages/board-server/src/server/home/index.ts deleted file mode 100644 index 487c70f352c..00000000000 --- a/packages/board-server/src/server/home/index.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { IncomingMessage, ServerResponse } from "http"; -import packageInfo from "../../../package.json" with { type: "json" }; - -import { getStore } from "../store.js"; - -export const serveHome = async ( - req: IncomingMessage, - res: ServerResponse -): Promise => { - // The "localhost" here isn't used for anything, it's just a placeholder to - // help us parse the rest of the URL. - const url = new URL(req.url ?? "", "http://localhost"); - if (url.pathname !== "/") { - return false; - } - - const store = getStore(); - const info = await store.getServerInfo(); - const title = info?.title ?? "Board Server"; - const description = - info?.description ?? - `A server that hosts Breadboard boards.`; - res.end(` - - ${title} - -

    ${title}

    -

    ${description}

    -

    Version: ${packageInfo.version}

    - - `); - return true; -}; diff --git a/packages/board-server/src/server/info/index.ts b/packages/board-server/src/server/info/index.ts deleted file mode 100644 index 09bade0aece..00000000000 --- a/packages/board-server/src/server/info/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { IncomingMessage, ServerResponse } from "http"; -import { getStore, type ServerInfo } from "../store.js"; -import { methodNotAllowed } from "../errors.js"; -import { corsAll } from "../cors.js"; -import packageInfo from "../../../package.json" with { type: "json" }; - -const DEFAULT_SERVER_INFO: ServerInfo = { - title: "Board Server", - description: "A server for Breadboard boards", - capabilities: { - boards: { - path: "/boards", - read: "open", - write: "key", - }, - }, -}; - -export const serveInfoAPI = async ( - req: IncomingMessage, - res: ServerResponse -): Promise => { - const path = req.url; - const isInfo = path === "/info"; - if (!isInfo) { - return false; - } - - if (!corsAll(req, res)) { - return true; - } - - if (req.method !== "GET") { - methodNotAllowed(res, "Only GET is allowed for /info"); - return true; - } - - const store = getStore(); - const info = (await store.getServerInfo()) || DEFAULT_SERVER_INFO; - const version = packageInfo.version; - - res.setHeader("Content-Type", "application/json"); - res.end(JSON.stringify({ ...info, version })); - - return true; -}; diff --git a/packages/board-server/src/server/proxy/index.ts b/packages/board-server/src/server/proxy/index.ts deleted file mode 100644 index 1d0e1aa83e3..00000000000 --- a/packages/board-server/src/server/proxy/index.ts +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { IncomingMessage, ServerResponse } from "http"; -import { methodNotAllowed, serverError } from "../errors.js"; -import { buildSecretsTunnel, secretsKit } from "./secrets.js"; -import { - ProxyServer, - type ServerResponse as ProxyServerResponse, - type AnyProxyRequestMessage, - HTTPServerTransport, - type ProxyServerConfig, -} from "@google-labs/breadboard/remote"; -import { asRuntimeKit } from "@google-labs/breadboard"; -import Core from "@google-labs/core-kit"; -import { getDataStore } from "@breadboard-ai/data-store"; -import type { ServerConfig } from "../config.js"; -import { cors } from "../cors.js"; -import { getUserKey } from "../auth.js"; -import { timestamp } from "../boards/utils/run-board.js"; - -class ResponseAdapter implements ProxyServerResponse { - #response: ServerResponse; - - constructor(response: ServerResponse) { - this.#response = response; - } - - header(field: string, value: string): unknown { - this.#response.setHeader(field, value); - return this; - } - - write(chunk: unknown): boolean { - return this.#response.write(chunk); - } - - end(): unknown { - this.#response.end(); - return this; - } -} - -const extractRequestBody = async (request: IncomingMessage) => { - return new Promise((resolve, reject) => { - let body = ""; - request.on("data", (chunk) => { - body += chunk.toString(); - }); - request.on("end", () => { - resolve(JSON.parse(body) as AnyProxyRequestMessage); - }); - request.on("error", reject); - }); -}; - -export const serveProxyAPI = async ( - serverConfig: ServerConfig, - req: IncomingMessage, - res: ServerResponse -) => { - const url = new URL(req.url || "", serverConfig.hostname); - const isProxy = url.pathname === "/proxy" || url.pathname === "/proxy/"; - if (!isProxy) { - return false; - } - - if (!cors(req, res, serverConfig.allowedOrigins)) { - return true; - } - - if (!getUserKey(req)) { - // Output the error in node proxy response format. - res.setHeader("Content-Type", "application/json"); - res.statusCode = 401; - res.end( - JSON.stringify([ - "error", - { - error: "Need a valid server key to access the node proxy.", - timestamp: timestamp(), - }, - ]) - ); - return true; - } - - if (req.method !== "POST") { - methodNotAllowed(res, "Use POST method"); - return true; - } - - const body = await extractRequestBody(req); - const server = new ProxyServer( - new HTTPServerTransport({ body }, new ResponseAdapter(res)) - ); - const store = getDataStore(); - store.createGroup("run-board"); - - const tunnel = await buildSecretsTunnel(); - const config: ProxyServerConfig = { - kits: [secretsKit, asRuntimeKit(Core)], - store, - proxy: ["fetch", { node: "secrets", tunnel }], - }; - - try { - await server.serve(config); - } catch (e) { - serverError(res, (e as Error).message); - } - - store.releaseAll(); - - return true; -}; diff --git a/packages/board-server/src/server/proxy/secrets.ts b/packages/board-server/src/server/proxy/secrets.ts deleted file mode 100644 index 55faacad422..00000000000 --- a/packages/board-server/src/server/proxy/secrets.ts +++ /dev/null @@ -1,248 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { SecretManagerServiceClient } from "@google-cloud/secret-manager"; -import type { Kit } from "@google-labs/breadboard"; -import type { SecretInputs } from "../types.js"; -import { hasOrigin, type TunnelSpec } from "@google-labs/breadboard/remote"; -import { fileURLToPath } from "url"; -import { dirname, resolve } from "path"; -import { readFile } from "fs/promises"; - -const MODULE_PATH = dirname(fileURLToPath(import.meta.url)); -const ROOT_PATH = resolve(MODULE_PATH, "../../../.."); - -export type SecretsStore = { - getList: () => Promise; - getKey( - key: string - ): Promise<[name: string, value: string, origin?: string | null] | null>; -}; - -export type SecretMapEntry = { - secret: string; - origin: string | null; -}; - -export const buildSecretsTunnel = async (): Promise => { - const secrets = await SecretsProvider.instance().getList(); - return Object.fromEntries( - secrets.map(({ secret, origin }) => { - return [ - secret, - { - to: "fetch", - when: { - url: hasOrigin(origin!), - }, - }, - ]; - }) - ); -}; - -class SecretManagerProvider implements SecretsStore { - #projectId: Promise; - #secretManager = new SecretManagerServiceClient(); - #secretsMap = new Map(); - - constructor() { - this.#projectId = this.#getProjectId(); - } - - async #getProjectId() { - let projectId = process.env.GOOGLE_CLOUD_PROJECT; - if (projectId) return projectId; - - const service = process.env.K_SERVICE; - if (service) { - // Try metadata paths for Cloud Run. - const metadataServer = "http://metadata.google.internal"; - const projectIdPath = "/computeMetadata/v1/project/project-id"; - try { - const response = await fetch(`${metadataServer}${projectIdPath}`, { - headers: { - "Metadata-Flavor": "Google", - }, - }); - projectId = await response.text(); - } catch (e) { - throw new Error( - `Failed to fetch project ID from metadata server: ${e}` - ); - } - } - if (!projectId) { - throw new Error("Please set GOOGLE_CLOUD_PROJECT environment variable."); - } - return projectId; - } - - async #getAnnotation(name: string) { - const projectId = await this.#projectId; - const secretName = this.#secretManager.secretPath(projectId, name); - const [secret] = await this.#secretManager.getSecret({ name: secretName }); - if (!secret) { - throw new Error(`Missing secret: ${name}`); - } - const origin = secret.annotations?.["origin"] || null; - return origin; - } - - async getList(): Promise { - const projectId = await this.#projectId; - try { - const [secrets] = await this.#secretManager.listSecrets({ - parent: `projects/${projectId}`, - }); - const secretNames = secrets - .map((s) => s.name?.split("/").pop()) - .filter(Boolean) as string[]; - const entries = await Promise.all( - secretNames.map(async (name) => { - const origin = await this.#getAnnotation(name); - if (!origin) { - return null; - } - return { secret: name, origin }; - }) - ); - return entries.filter(Boolean) as SecretMapEntry[]; - } catch (e) { - throw new Error(`Failed to list secrets: ${e}`); - } - } - - async getKey( - key: string - ): Promise<[name: string, value: string, origin?: string | null] | null> { - if (this.#secretsMap.has(key)) { - const entry = this.#secretsMap.get(key); - return [key, entry?.secret as string, entry?.origin]; - } - const projectId = await this.#projectId; - const name = this.#secretManager.secretVersionPath( - projectId, - key, - "latest" - ); - const secretName = this.#secretManager.secretPath(projectId, key); - try { - const [secret] = await this.#secretManager.getSecret({ - name: secretName, - }); - const origin = secret.annotations?.["origin"] || null; - const [version] = await this.#secretManager.accessSecretVersion({ name }); - const payload = version?.payload?.data; - if (!payload) { - throw new Error(`Missing secret: ${key}`); - } - const value = payload.toString(); - this.#secretsMap.set(key, { secret: value, origin }); - return [key, value, origin]; - } catch (e) { - throw new Error(`Failed to get secret: ${key}`); - } - } -} - -class SimpleSecretsProvider implements SecretsStore { - #secrets: Promise>; - - constructor() { - this.#secrets = this.#readSecretsFile(); - } - - async #readSecretsFile() { - const secretsFile = resolve(ROOT_PATH, "secrets.json"); - try { - const data = await readFile(secretsFile, "utf-8"); - const parsed = JSON.parse(data) as Record; - if (typeof parsed !== "object") { - throw new Error(`Invalid secrets file: ${secretsFile}`); - } - if ( - Object.values(parsed).some( - (entry) => - typeof entry !== "object" || (!entry.secret && !entry.origin) - ) - ) { - throw new Error(`Invalid secrets file: ${secretsFile}`); - } - - return parsed; - } catch (e) { - throw new Error(`Failed to load secrets file: ${e}`); - } - } - - async getList(): Promise { - const secrets = await this.#secrets; - return Object.entries(secrets).map(([secret, { origin }]) => ({ - secret, - origin, - })); - } - - async getKey( - key: string - ): Promise<[name: string, value: string, origin?: string | null] | null> { - const secrets = await this.#secrets; - const entry = secrets[key]; - if (!entry) { - throw new Error(`Failed to get secret: ${key}`); - } - return [key, entry.secret, entry.origin]; - } -} - -class SecretsProvider implements SecretsStore { - #store: SecretsStore; - - constructor() { - let backend = process.env.STORAGE_BACKEND; - if (backend && backend !== "firestore") { - this.#store = new SimpleSecretsProvider(); - } else { - this.#store = new SecretManagerProvider(); - } - this.getKey = this.getKey.bind(this); - } - - getList(): Promise { - return this.#store.getList(); - } - - getKey( - key: string - ): Promise<[name: string, value: string, origin?: string | null] | null> { - return this.#store.getKey(key); - } - - static #instance: SecretsProvider | null = null; - static instance() { - if (!SecretsProvider.#instance) { - SecretsProvider.#instance = new SecretsProvider(); - } - return SecretsProvider.#instance; - } -} - -/** - * The simplest possible Kit that contains a "secrets" node that talks to the - * Google Cloud Secret Manager. - */ -export const secretsKit: Kit = { - url: import.meta.url, - handlers: { - secrets: async (inputs) => { - const getKey = SecretsProvider.instance().getKey; - const { keys } = inputs as SecretInputs; - const entries = await Promise.all(keys.map(getKey)); - return Object.fromEntries(entries as [string, string][]); - }, - }, -}; diff --git a/packages/board-server/src/server/storage-providers/firestore.ts b/packages/board-server/src/server/storage-providers/firestore.ts deleted file mode 100644 index 4dbbbb1a7b5..00000000000 --- a/packages/board-server/src/server/storage-providers/firestore.ts +++ /dev/null @@ -1,269 +0,0 @@ -import { Firestore } from "@google-cloud/firestore"; -import { type ReanimationState, type GraphDescriptor, blankLLMContent } from "@google-labs/breadboard"; -import { EXPIRATION_TIME_MS, type ServerInfo, type GetUserStoreResult, type BoardListEntry, asPath, type OperationResult, asInfo, sanitize, INVITE_EXPIRATION_TIME_MS } from "../store.js"; -import type { BoardServerStore, CreateInviteResult, CreateUserResult, ListInviteResult, RunBoardStateStore } from "../types.js"; - - -const REANIMATION_COLLECTION_ID = "resume"; - -export class FirestoreStorageProvider implements RunBoardStateStore, BoardServerStore { - #database; - - constructor(storeName: string) { - this.#database = new Firestore({ - databaseId: storeName, - }); - } - - async createUser(username: string, apiKey: string): Promise { - const existing = await this.#database.doc(`users/${username}`).get(); - if (existing.exists) { - console.error( - `Account ${username} already exists with API key:\n${existing.data()!.apiKey}` - ); - process.exit(0); - } - - await this.#database.doc(`users/${username}`).set({ apiKey: apiKey }); - - return { success: true, apiKey } - } - - #getReanimationStateDoc(user: string, ticket?: string) { - const collection = this.#database - .collection("runs") - .doc(user) - .collection(REANIMATION_COLLECTION_ID); - if (ticket) { - return collection.doc(ticket); - } - return collection.doc(); - } - - async saveReanimationState( - user: string, - state: ReanimationState - ): Promise { - const timestamp = new Date(); - const expireAt = new Date(timestamp.getTime() + EXPIRATION_TIME_MS); - const docRef = this.#getReanimationStateDoc(user); - await docRef.set({ state: JSON.stringify(state), timestamp, expireAt }); - return docRef.id; - } - - async loadReanimationState( - user: string, - ticket: string - ): Promise { - const data = await this.#getReanimationStateDoc(user, ticket).get(); - if (!data.exists) { - return undefined; - } - const state = JSON.parse(data.get("state")); - if (!state.states) { - return undefined; - } - return state; - } - - async getServerInfo(): Promise { - const data = await this.#database - .collection("configuration") - .doc("metadata") - .get(); - return data.data() as ServerInfo | undefined; - } - - async getUserStore(userKey: string | null): Promise { - if (!userKey) { - return { success: false, error: "No user key supplied" }; - } - const users = this.#database.collection(`users`); - const key = await users.where("apiKey", "==", userKey).get(); - if (key.empty) { - return { success: false, error: "User not found" }; - } - const doc = key.docs[0]; - if (!doc) { - return { success: false, error: "User not found" }; - } - return { success: true, store: doc.id }; - } - - async list(userKey: string | null): Promise { - const userStoreResult = await this.getUserStore(userKey); - const userStore = userStoreResult.success ? userStoreResult.store : null; - - const allStores = await this.#database - .collection("workspaces") - .listDocuments(); - const boards = []; - for (const store of allStores) { - const docs = await store.collection("boards").get(); - const storeBoards: BoardListEntry[] = []; - docs.forEach((doc) => { - const path = asPath(store.id, doc.id); - const title = doc.get("title") || path; - const tags = (doc.get("tags") as string[]) || ["published"]; - const published = tags.includes("published"); - const readonly = userStore !== store.id; - const mine = userStore === store.id; - const username = store.id; - if (!published && !mine) { - return; - } - storeBoards.push({ title, path, username, readonly, mine, tags }); - }); - boards.push(...storeBoards); - } - return boards; - } - - async get(userStore: string, boardName: string): Promise { - const doc = await this.#database - .doc(`workspaces/${userStore}/boards/${boardName}`) - .get(); - return doc.get("graph"); - } - - async update( - userStore: string, - path: string, - graph: GraphDescriptor - ): Promise { - const { userStore: pathUserStore, boardName } = asInfo(path); - if (pathUserStore !== userStore) { - return { success: false, error: "Unauthorized" }; - } - const { title: maybeTitle, metadata } = graph; - const tags = metadata?.tags || []; - const title = maybeTitle || boardName; - - await this.#database - .doc(`workspaces/${userStore}/boards/${boardName}`) - .set({ graph: JSON.stringify(graph), tags, title }); - return { success: true }; - } - - async create(userKey: string, name: string, dryRun = false): Promise<{success: boolean, path: string | undefined, error: string | undefined}> { - const userStore = await this.getUserStore(userKey); - if (!userStore.success) { - return { success: false, path: undefined, error: userStore.error }; - } - // The format for finding the unique name is {name}-copy[-number]. - // We'll first start with the sanitized name, then move on to {name}-copy. - // If that's taken, we'll try {name}-copy-2, {name}-copy-3, etc. - // Start with a board name proposal based on the sanitized name. - let proposal = sanitize(name); - let copyNumber = 0; - for (;;) { - // Check if the proposed name is already taken. - const doc = await this.#database - .doc(`workspaces/${userStore.store}/boards/${proposal}.bgl.json`) - .get(); - if (!doc.exists) { - break; - } - if (copyNumber === 0) { - // If the name is taken, add "-copy" to the end and try again. - proposal = `${proposal}-copy`; - } else if (copyNumber === 1) { - proposal = `${proposal}-${copyNumber + 1}`; - } else { - // Slice off the "number" part of the name. - proposal = proposal.slice(0, -2); - // Add the next number to the end of the name. - proposal = `${proposal}-${copyNumber + 1}`; - } - copyNumber++; - } - if (!dryRun) { - // Create a blank board with the proposed name. - await this.#database - .doc(`workspaces/${userStore.store}/boards/${proposal}.bgl.json`) - .set({ graph: blankLLMContent() }); - } - const path = asPath(userStore.store, `${proposal}.bgl.json`); - return { success: true, path, error: undefined }; - } - - async delete(userStore: string, path: string): Promise { - const { userStore: pathUserStore, boardName } = asInfo(path); - if (pathUserStore !== userStore) { - return { success: false, error: "Unauthorized" }; - } - await this.#database - .doc(`workspaces/${userStore}/boards/${boardName}`) - .delete(); - return { success: true }; - } - - async findInvite( - userStore: string, - boardName: string, - invite: string - ): Promise { - const invites = this.#database.collection( - `workspaces/${userStore}/boards/${boardName}/invites` - ); - const inviteDoc = await invites.where("invite", "==", invite).get(); - if (inviteDoc.empty) { - return { success: false, error: "Board or invite not found" }; - } - return { success: true }; - } - - async createInvite( - userStore: string, - path: string - ): Promise { - const { userStore: pathUserStore, boardName } = asInfo(path); - if (pathUserStore !== userStore) { - return { - success: false, - error: "This user can't create invite for this board.", - }; - } - const invite = Math.random().toString(36).slice(2, 10); - const expireAt = new Date(Date.now() + INVITE_EXPIRATION_TIME_MS); - await this.#database - .doc(`workspaces/${userStore}/boards/${boardName}/invites/${invite}`) - .set({ invite, expireAt }); - return { success: true, invite }; - } - - async deleteInvite( - userStore: string, - path: string, - invite: string - ): Promise { - const { userStore: pathUserStore, boardName } = asInfo(path); - if (pathUserStore !== userStore) { - return { - success: false, - error: "This user can't delete invite for this board.", - }; - } - await this.#database - .doc(`workspaces/${userStore}/boards/${boardName}/invites/${invite}`) - .delete(); - return { success: true }; - } - - async listInvites( - userStore: string, - path: string - ): Promise { - const { userStore: pathUserStore, boardName } = asInfo(path); - if (pathUserStore !== userStore) { - return { - success: false, - error: "This user can't list invites for this board.", - }; - } - const invites = await this.#database - .collection(`workspaces/${userStore}/boards/${boardName}/invites`) - .get(); - return { success: true, invites: invites.docs.map((doc) => doc.id) }; - } - } \ No newline at end of file diff --git a/packages/board-server/src/server/storage-providers/sqlite.ts b/packages/board-server/src/server/storage-providers/sqlite.ts deleted file mode 100644 index 45d02b7a22c..00000000000 --- a/packages/board-server/src/server/storage-providers/sqlite.ts +++ /dev/null @@ -1,416 +0,0 @@ -import Database from "better-sqlite3"; -import type { CreateInviteResult, CreateUserResult, ListInviteResult, RunBoardStateStore, BoardServerStore } from "../types.js"; -import type { BoardListEntry, GetUserStoreResult, OperationResult, ServerInfo } from "../store.js"; -import { asInfo, asPath, EXPIRATION_TIME_MS, INVITE_EXPIRATION_TIME_MS, sanitize } from "../store.js"; -import type { GraphDescriptor, ReanimationState } from "@google-labs/breadboard"; -import { v4 as uuidv4 } from 'uuid'; - -export class SQLiteStorageProvider implements RunBoardStateStore, BoardServerStore { - private db: Database.Database; - - constructor(dbPath: string) { - this.db = new Database(dbPath); - - // Initialize tables - this.db.exec(` - CREATE TABLE IF NOT EXISTS reanimation_states ( - id TEXT PRIMARY KEY, - user TEXT NOT NULL, - state TEXT NOT NULL, - timestamp INTEGER NOT NULL, - expire_at INTEGER NOT NULL - ); - - CREATE TABLE IF NOT EXISTS users ( - id TEXT PRIMARY KEY, - api_key TEXT NOT NULL UNIQUE - ); - - CREATE TABLE IF NOT EXISTS workspaces ( - id TEXT PRIMARY KEY - ); - - CREATE TABLE IF NOT EXISTS boards ( - workspace_id TEXT, - board_id TEXT, - title TEXT, - tags TEXT, - graph TEXT, - PRIMARY KEY (workspace_id, board_id), - FOREIGN KEY (workspace_id) REFERENCES workspaces(id) - ); - - CREATE TABLE IF NOT EXISTS invites ( - workspace_id TEXT, - board_id TEXT, - invite TEXT, - expire_at INTEGER, - PRIMARY KEY (workspace_id, board_id, invite), - FOREIGN KEY (workspace_id, board_id) REFERENCES boards(workspace_id, board_id) - ); - - CREATE TABLE IF NOT EXISTS configuration ( - key TEXT PRIMARY KEY, - value TEXT - ); - `); - } - - async saveReanimationState(user: string, state: ReanimationState): Promise { - const timestamp = Date.now(); - const expireAt = timestamp + EXPIRATION_TIME_MS; - const id = uuidv4(); // Generate a UUID - - const stmt = this.db.prepare(` - INSERT INTO reanimation_states (id, user, state, timestamp, expire_at) - VALUES (?, ?, ?, ?, ?) - `); - - stmt.run(id, user, JSON.stringify(state), timestamp, expireAt); - - return id; - } - - async loadReanimationState(user: string, ticket: string): Promise { - const stmt = this.db.prepare(` - SELECT state FROM reanimation_states - WHERE user = ? AND id = ? AND expire_at > ? - `); - - const row: any = stmt.get(user, ticket, Date.now()); - if (!row) { - return undefined; - } - - const state = JSON.parse(row.state); - if (!state.states) { - return undefined; - } - - return state; - } - - async getServerInfo(): Promise { - const stmt = this.db.prepare(` - SELECT value FROM configuration - WHERE key = ? - `); - - const row: any = stmt.get('metadata'); - if (!row) { - return undefined; - } - - try { - return JSON.parse(row.value); - } catch (error) { - console.error('Error parsing server info:', error); - return undefined; - } - } - - async getUserStore(userKey: string | null): Promise { - if (!userKey) { - return { success: false, error: "No user key supplied" }; - } - const stmt = this.db.prepare(` - SELECT id FROM users - WHERE api_key = ? - `); - const row: any = stmt.get(userKey); - if (!row) { - return { success: false, error: "User not found" }; - } - return { success: true, store: row.id }; - } - - async list(userKey: string | null): Promise { - const userStoreResult = await this.getUserStore(userKey); - const userStore = userStoreResult.success ? userStoreResult.store : null; - - const allStoresStmt = this.db.prepare(` - SELECT id FROM workspaces - `); - const allStores: any[] = allStoresStmt.all(); - - const boards: BoardListEntry[] = []; - for (const store of allStores) { - const docsStmt = this.db.prepare(` - SELECT board_id, title, tags FROM boards - WHERE workspace_id = ? - `); - const docs: any[] = docsStmt.all(store.id); - - for (const doc of docs) { - const path = `${store.id}/${doc.board_id}`; - const title = doc.title || path; - const tags = doc.tags as string[] || []; - const published = tags.includes("published"); - const readonly = userStore !== store.id; - const mine = userStore === store.id; - const username = store.id; - if (!published && !mine) { - continue; - } - boards.push({ title, path, username, readonly, mine, tags }); - } - } - return boards; - } - - async get(userStore: string, boardName: string): Promise { - // Prepare and execute the SQL query to get the board details - const stmt = this.db.prepare(` - SELECT graph FROM boards - WHERE workspace_id = ? AND board_id = ? - `); - const row: any = stmt.get(userStore, boardName); - - // Return the 'graph' column data if it exists, or undefined if not found - return row.graph; - } - - async update( - userStore: string, - path: string, - graph: GraphDescriptor - ): Promise { - const { userStore: pathUserStore, boardName } = asInfo(path); - if (pathUserStore !== userStore) { - return { success: false, error: "Unauthorized" }; - } - - const { title: maybeTitle, metadata } = graph; - const tags = metadata?.tags || []; - const title = maybeTitle || boardName; - - // Convert tags array to a comma-separated string for storage - const tagsString = tags.join(','); - - try { - const stmt = this.db.prepare(` - INSERT INTO boards (workspace_id, board_id, title, tags, graph) - VALUES (?, ?, ?, ?, ?) - ON CONFLICT(workspace_id, board_id) - DO UPDATE SET title = excluded.title, tags = excluded.tags, graph = excluded.graph - `); - stmt.run(userStore, boardName, title, tagsString, JSON.stringify(graph)); - - return { success: true }; - } catch (error) { - console.error('Error updating board:', error); - return { success: false, error: 'Update failed' }; - } - } - - async create(userKey: string, name: string, dryRun = false): Promise<{success: boolean, path: string | undefined, error: string | undefined}> { - const userStoreResult = await this.getUserStore(userKey); - if (!userStoreResult.success) { - return { success: false, path: undefined, error: userStoreResult.error }; - } - const userStore = userStoreResult.store!; - - // The format for finding the unique name is {name}-copy[-number]. - let proposal = sanitize(name); - let copyNumber = 0; - - // Check for existing board names - while (true) { - const stmt = this.db.prepare("SELECT 1 FROM boards WHERE workspace_id = ? AND board_id = ?"); - const exists = stmt.get(userStore, proposal); - - if (!exists) { - break; - } - - if (copyNumber === 0) { - proposal = `${proposal}-copy`; - } else if (copyNumber === 1) { - proposal = `${proposal}-${copyNumber + 1}`; - } else { - proposal = proposal.slice(0, -2); // Remove last "-number" - proposal = `${proposal}-${copyNumber + 1}`; - } - - copyNumber++; - } - - if (!dryRun) { - // Create a blank board with the proposed name - const stmt = this.db.prepare(` - INSERT INTO boards (workspace_id, board_id, title, tags, graph) - VALUES (?, ?, ?, ?, ?) - `); - stmt.run(userStore, proposal, proposal, '', JSON.stringify({})); // Empty title, tags, and graph - } - - const path = asPath(userStore, `${proposal}.bgl.json`); - return { success: true, path, error: undefined }; - } - - async delete(userStore: string, path: string): Promise<{ success: boolean; error?: string }> { - const { userStore: pathUserStore, boardName } = asInfo(path); - - // Check authorization - if (pathUserStore !== userStore) { - return { success: false, error: "Unauthorized" }; - } - - // Delete the board - const stmt = this.db.prepare(` - DELETE FROM boards - WHERE workspace_id = ? AND board_id = ? - `); - const result = stmt.run(userStore, boardName); - - // Check if the deletion was successful - if (result.changes > 0) { - return { success: true }; - } else { - return { success: false, error: "Board not found" }; - } - } - - async findInvite( - userStore: string, - boardName: string, - invite: string - ): Promise<{ success: boolean; error?: string }> { - // Prepare and execute SQL query - const stmt = this.db.prepare(` - SELECT 1 - FROM invites - WHERE workspace_id = ? AND board_id = ? AND invite = ? - `); - const row: any = stmt.get(userStore, boardName, invite); - - // Check if invite exists - if (row) { - return { success: true }; - } else { - return { success: false, error: "Board or invite not found" }; - } - } - - async createInvite( - userStore: string, - path: string - ): Promise { - const { userStore: pathUserStore, boardName } = asInfo(path); - if (pathUserStore !== userStore) { - return { - success: false, - error: "This user can't create invite for this board.", - }; - } - - const invite = Math.random().toString(36).slice(2, 10); - const expireAt = Date.now() + INVITE_EXPIRATION_TIME_MS; - - // Check if invite already exists - const existingInvite = await this.findInvite(userStore, boardName!, invite) - - if (existingInvite.success) { - return { success: false, error: "Invite already exists." }; - } - - // Insert new invite - const stmt = this.db.prepare(` - INSERT INTO invites (workspace_id, board_id, invite, expire_at) - VALUES (?, ?, ?, ?) - `); - try { - stmt.run(userStore, boardName, invite, expireAt); - return { success: true, invite }; - } catch (error) { - return { success: false, error: "Failed to create invite." }; - } - } - - async deleteInvite( - userStore: string, - path: string, - invite: string - ): Promise { - const { userStore: pathUserStore, boardName } = asInfo(path); - if (pathUserStore !== userStore) { - return { - success: false, - error: "This user can't delete invite for this board.", - }; - } - - const stmt = this.db.prepare(` - DELETE FROM invites - WHERE workspace_id = ? AND board_id = ? AND invite = ? - `); - - try { - const result = stmt.run(userStore, boardName, invite); - // Check if any rows were affected - if (result.changes === 0) { - return { success: false, error: "Invite not found or already deleted." }; - } - return { success: true }; - } catch (error) { - return { success: false, error: "Failed to delete invite." }; - } - } - - async listInvites( - userStore: string, - path: string - ): Promise { - const { userStore: pathUserStore, boardName } = asInfo(path); - if (pathUserStore !== userStore) { - return { - success: false, - error: "This user can't list invites for this board.", - }; - } - - const stmt = this.db.prepare(` - SELECT invite FROM invites - WHERE workspace_id = ? AND board_id = ? - `); - - try { - const rows: any[] = stmt.all(userStore, boardName); - const invites = rows.map(row => row.invite); - return { success: true, invites }; - } catch (error) { - return { success: false, error: "Failed to list invites." }; - } - } - - async createUser(username: string, apiKey: string): Promise { - return new Promise((resolve) => { - try { - // Check if the user already exists - const checkStmt = this.db.prepare('SELECT api_key FROM users WHERE id = ?'); - const existingUser = checkStmt.get(username); - - if (existingUser) { - resolve({ - success: false, - message: `Account ${username} already exists with API key:\n${existingUser}` - }); - return; - } - - // Insert new user - const userInsertStmt = this.db.prepare('INSERT INTO users (id, api_key) VALUES (?, ?)'); - userInsertStmt.run(username, apiKey); - - // Insert workspace - const wsInsertStmt = this.db.prepare('INSERT INTO workspaces (id) VALUES (?)'); - wsInsertStmt.run(username); - - resolve({ success: true, apiKey }); - } catch (error: any) { - resolve({ success: false, message: error.message }); - } - }); - } - } - \ No newline at end of file diff --git a/packages/board-server/src/server/store.ts b/packages/board-server/src/server/store.ts deleted file mode 100644 index 1c06a741da3..00000000000 --- a/packages/board-server/src/server/store.ts +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { SQLiteStorageProvider } from "./storage-providers/sqlite.js"; -import { FirestoreStorageProvider } from "./storage-providers/firestore.js"; - -export const EXPIRATION_TIME_MS = 1000 * 60 * 60 * 24 * 2; // 2 days -export const INVITE_EXPIRATION_TIME_MS = 1000 * 60 * 60 * 24 * 4; // 4 days - -export type GetUserStoreResult = - | { success: true; store: string } - | { success: false; error: string }; - -export type OperationResult = - | { success: true } - | { success: false; error: string }; - -// Use factories here, so that the providers are only instantiated -// when chosen. -const providers = { - sqlite: () => - new SQLiteStorageProvider( - process.env["SQLITE_DB_PATH"] || "board-server.db" - ), - firestore: () => new FirestoreStorageProvider("board-server"), -}; - -export const getStore = () => { - const backend = process.env["STORAGE_BACKEND"]; - const provider = providers[backend === "sqlite" ? "sqlite" : "firestore"]; - return provider(); -}; - -const createAPIKey = async () => { - const uuid = crypto.randomUUID(); - const data = new TextEncoder().encode(uuid); - const digest = await crypto.subtle.digest("SHA-256", data); - const hashArray = Array.from(new Uint8Array(digest)); - const hashHex = hashArray.map((b) => b.toString(36)).join(""); - return `bb-${hashHex.slice(0, 50)}`; -}; - -export async function createAccount(username: string) { - const store = getStore(); - - const key = await createAPIKey(); - - await store!.createUser(username, key); - - return { account: username, api_key: key }; -} - -export type BoardListEntry = { - title: string; - path: string; - username: string; - readonly: boolean; - mine: boolean; - tags: string[]; -}; - -export type ServerCapabilityAccess = "open" | "key"; - -export type ServerCapabilityInfo = { - path: string; - read: ServerCapabilityAccess; - write: ServerCapabilityAccess; -}; - -export type ServerCapability = "boards" | "proxy"; - -export type ServerInfo = { - title?: string; - description?: string; - capabilities?: Partial>; -}; - -export const asPath = (userStore: string, boardName: string) => { - return `@${userStore}/${boardName}`; -}; - -export const sanitize = (name: string) => { - if (name.endsWith(".bgl.json")) { - name = name.slice(0, -9); - } else if (name.endsWith(".json")) { - name = name.slice(0, -5); - } - name = name.replace(/[^a-zA-Z0-9]/g, "-"); - return name; -}; - -export const asInfo = (path: string) => { - const [userStore, boardName] = path.split("/"); - if (!userStore || userStore[0] !== "@") { - return {}; - } - return { userStore: userStore.slice(1), boardName }; -}; diff --git a/packages/board-server/src/server/types.ts b/packages/board-server/src/server/types.ts deleted file mode 100644 index 81d1c9b7f93..00000000000 --- a/packages/board-server/src/server/types.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - GraphDescriptor, - InputValues, - Kit, - ReanimationState, -} from "@google-labs/breadboard"; -import type { RunDiagnosticsLevel } from "@google-labs/breadboard/harness"; -import type { RemoteMessageWriter } from "@google-labs/breadboard/remote"; -import type { IncomingMessage, ServerResponse } from "http"; -import type { BoardListEntry, GetUserStoreResult, OperationResult, ServerInfo } from "./store.js"; - -export type GeneralRequestType = "list" | "create"; - -export type UserRequestType = - | "list" - | "create" - | "get" - | "update" - | "app" - | "api" - | "invoke" - | "describe" - | "run" - | "invite-list" - | "invite-update"; - -export type RequestType = GeneralRequestType | UserRequestType; - -export type GeneralParseResult = { - success: true; - type: GeneralRequestType; -}; - -export type BoardParseResult = { - success: true; - type: UserRequestType; - board: string; - url: string; - user: string; - name: string; -}; - -export type ParseResult = - | GeneralParseResult - | BoardParseResult - | { success: false; error: string; code: number }; - -export type ApiHandler = ( - parsed: T, - req: IncomingMessage, - res: ServerResponse, - body?: unknown -) => Promise; - -export type SecretInputs = { - keys: string[]; -}; - -export type BoardServerLoadFunction = ( - path: string -) => Promise; - -export type InvokeBoardArguments = { - url: string; - path: string; - loader: BoardServerLoadFunction; - inputs: Record; - kitOverrides?: Kit[]; -}; - -export type RunBoardArguments = { - /** - * The full URL or the requested board, like - * `https://board.server/boards/@user/board.bgl.json`. - */ - url: string; - /** - * The path to the board, like `@user/board.bgl.json`. - */ - path: string; - /** - * The user who is running the board. - */ - user: string; - /** - * The function that supplies the actual board given the path. - */ - loader: BoardServerLoadFunction; - /** - * The state store for graph reanimation. - */ - runStateStore: RunBoardStateStore; - /** - * The writer for the results of the board run. - */ - writer: RemoteMessageWriter; - inputs?: InputValues; - kitOverrides?: Kit[]; - next?: string; - diagnostics?: RunDiagnosticsLevel; -}; - -export type RunBoardStateStore = { - loadReanimationState( - user: string, - ticket: string - ): Promise; - saveReanimationState(user: string, state: ReanimationState): Promise; -}; - -export type BoardServerStore = { - getServerInfo(): Promise - createUser(username: string, apiKey: string): Promise - list(userKey: string | null): Promise - getUserStore(userKey: string | null): Promise - get(userStore: string, boardName: string): Promise - update(userStore: string, path: string, graph: GraphDescriptor): Promise - create(userKey: string, name: string, dryRun: boolean): Promise -}; - -export type CreateBoardResult = {success: boolean, path: string | undefined, error: string | undefined} - -export type CreateUserResult = - | { success: true; apiKey: string } - | { success: false; message: string }; - -export type CreateInviteResult = - | { - success: true; - invite: string; - } - | { - success: false; - error: string; - }; - -export type ListInviteResult = - | { - success: true; - invites: string[]; - } - | { - success: false; - error: string; - }; - -export type PageMetadata = { - title: string; - description: string; -}; diff --git a/packages/board-server/tests/board-api-parser.ts b/packages/board-server/tests/board-api-parser.ts deleted file mode 100644 index 91672a51d9d..00000000000 --- a/packages/board-server/tests/board-api-parser.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { - parse, - BoardAPIParser, -} from "../src/server/boards/utils/board-api-parser.js"; -import { deepStrictEqual, ok } from "assert"; -import data from "./parser-data.json" with { type: "json" }; - -describe("Board API Parser", () => { - test("recognizes Board API entry", (t) => { - ok( - new BoardAPIParser( - new URL("http://localhost/boards/foo"), - "GET" - ).isBoardURL() - ); - - ok( - new BoardAPIParser( - new URL("http://example.com/boards"), - "GET" - ).isBoardURL() - ); - - ok( - !new BoardAPIParser( - new URL("http://localhost/beards"), - "GET" - ).isBoardURL() - ); - }); - - test("parses Board API ", (t) => { - for (const { url, method, result } of data) { - deepStrictEqual(parse(new URL(url), method), result); - } - }); -}); diff --git a/packages/board-server/tests/boards/invoke-board-with-bubbling-input.bgl.json b/packages/board-server/tests/boards/invoke-board-with-bubbling-input.bgl.json deleted file mode 100644 index f2339f9ec02..00000000000 --- a/packages/board-server/tests/boards/invoke-board-with-bubbling-input.bgl.json +++ /dev/null @@ -1,212 +0,0 @@ -{ - "title": "Invoke Board with Bubbling Input", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "name": { - "type": "string", - "title": "Name", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -22, - "y": -37, - "collapsed": false - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "greeting": { - "type": "string", - "title": "Greeting", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 428, - "y": 30, - "collapsed": false - } - } - }, - { - "id": "invoke-b5fe388d", - "type": "invoke", - "metadata": { - "visual": { - "x": 125, - "y": -48, - "collapsed": false - }, - "title": "Invoker", - "logLevel": "debug" - }, - "configuration": { - "$board": "#382969d5-0908-4367-b09e-95d8b351c39b" - } - }, - { - "id": "promptTemplate-f586d280", - "type": "promptTemplate", - "metadata": { - "visual": { - "x": 175, - "y": 105, - "collapsed": false - }, - "title": "Wrapper", - "logLevel": "debug" - }, - "configuration": { - "template": "Greeting is: \"{{greeting}}\"" - } - } - ], - "edges": [ - { - "from": "input", - "to": "invoke-b5fe388d", - "out": "name", - "in": "name" - }, - { - "from": "invoke-b5fe388d", - "to": "promptTemplate-f586d280", - "out": "greeting", - "in": "greeting" - }, - { - "from": "promptTemplate-f586d280", - "to": "output", - "out": "prompt", - "in": "greeting" - } - ], - "graphs": { - "382969d5-0908-4367-b09e-95d8b351c39b": { - "title": "Template Maker", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "name": { - "type": "string", - "title": "Name", - "examples": [] - }, - "location": { - "type": "string", - "title": "Location", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -191, - "y": -11, - "collapsed": false - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "greeting": { - "type": "string", - "title": "Greeting", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 215, - "y": 8, - "collapsed": false - } - } - }, - { - "id": "promptTemplate-81f85b70", - "type": "promptTemplate", - "metadata": { - "visual": { - "x": 12, - "y": 7, - "collapsed": false - }, - "title": "Make Template", - "logLevel": "debug" - }, - "configuration": { - "template": "Hello, {{name}} from {{location}}!" - } - } - ], - "edges": [ - { - "from": "input", - "to": "promptTemplate-81f85b70", - "out": "name", - "in": "name" - }, - { - "from": "input", - "to": "promptTemplate-81f85b70", - "out": "location", - "in": "location" - }, - { - "from": "promptTemplate-81f85b70", - "to": "output", - "out": "prompt", - "in": "greeting" - } - ], - "metadata": { - "tags": [ - "tool" - ], - "comments": [] - }, - "url": "file://fsapi~boards/invoke-board-with-bubbling-input.bgl.json#382969d5-0908-4367-b09e-95d8b351c39b" - } - } -} \ No newline at end of file diff --git a/packages/board-server/tests/boards/just-output.bgl.json b/packages/board-server/tests/boards/just-output.bgl.json deleted file mode 100644 index 816c8b5286b..00000000000 --- a/packages/board-server/tests/boards/just-output.bgl.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "title": "just output", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "end": { - "type": "string", - "title": "The End", - "examples": [] - } - }, - "type": "object", - "required": [] - }, - "end": "END" - }, - "metadata": { - "visual": { - "x": 77, - "y": -11, - "collapsed": false - } - } - } - ], - "edges": [] -} \ No newline at end of file diff --git a/packages/board-server/tests/boards/many-inputs.bgl.json b/packages/board-server/tests/boards/many-inputs.bgl.json deleted file mode 100644 index 7a131041cc0..00000000000 --- a/packages/board-server/tests/boards/many-inputs.bgl.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "title": "many inputs", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "text1": { - "type": "string", - "title": "Text", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -64, - "y": 0, - "collapsed": false - }, - "title": "One", - "logLevel": "debug" - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "text-one": { - "type": "string", - "title": "Text One", - "examples": [] - }, - "text-two": { - "type": "string", - "title": "Text Two", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 215, - "y": 57, - "collapsed": false - } - } - }, - { - "id": "input-3c20cd3f", - "type": "input", - "metadata": { - "visual": { - "x": -63, - "y": 111, - "collapsed": false - }, - "title": "Two", - "logLevel": "debug" - }, - "configuration": { - "schema": { - "properties": { - "text2": { - "type": "string", - "title": "Text", - "examples": [] - } - }, - "type": "object", - "required": [] - } - } - } - ], - "edges": [ - { - "from": "input-3c20cd3f", - "to": "output", - "out": "text2", - "in": "text-two" - }, - { - "from": "input", - "to": "output", - "out": "text1", - "in": "text-one" - } - ], - "description": "", - "metadata": { - "tags": [], - "comments": [] - } -} \ No newline at end of file diff --git a/packages/board-server/tests/boards/many-outputs.bgl.json b/packages/board-server/tests/boards/many-outputs.bgl.json deleted file mode 100644 index 43567fbefa9..00000000000 --- a/packages/board-server/tests/boards/many-outputs.bgl.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "title": "many-outputs", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "start": { - "type": "string", - "title": "Start", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -159, - "y": 89, - "collapsed": false - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "one": { - "type": "string", - "title": "One", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 213, - "y": -24, - "collapsed": false - }, - "title": "One", - "logLevel": "debug" - } - }, - { - "type": "output", - "id": "output-83a8ab5e", - "configuration": { - "schema": { - "properties": { - "two": { - "type": "string", - "title": "Two", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 233, - "y": 169, - "collapsed": false - }, - "title": "Two", - "logLevel": "debug" - } - }, - { - "id": "runJavascript-fe3c9a41", - "type": "runJavascript", - "metadata": { - "visual": { - "x": 8, - "y": 44, - "collapsed": false - }, - "title": "Split", - "logLevel": "debug" - }, - "configuration": { - "code": "function run({start}) {\n return {\n \"one\": start,\n \"two\": start,\n }\n}", - "name": "run", - "raw": true - } - } - ], - "edges": [ - { - "from": "input", - "to": "runJavascript-fe3c9a41", - "out": "start", - "in": "start" - }, - { - "from": "runJavascript-fe3c9a41", - "to": "output", - "out": "one", - "in": "one" - }, - { - "from": "runJavascript-fe3c9a41", - "to": "output-83a8ab5e", - "out": "two", - "in": "two" - } - ], - "metadata": { - "comments": [] - } -} \ No newline at end of file diff --git a/packages/board-server/tests/boards/simple-published.bgl.json b/packages/board-server/tests/boards/simple-published.bgl.json deleted file mode 100644 index 8b98bc3222b..00000000000 --- a/packages/board-server/tests/boards/simple-published.bgl.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "title": "simple", - "version": "0.0.1", - "metadata": { - "comments": [], - "tags": [ - "published" - ] - }, - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "text": { - "type": "string", - "title": "Text", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -180, - "y": 62, - "collapsed": false - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "text": { - "type": "string", - "title": "Text", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 215, - "y": 57, - "collapsed": false - } - } - } - ], - "edges": [ - { - "from": "input", - "to": "output", - "out": "text", - "in": "text" - } - ] -} \ No newline at end of file diff --git a/packages/board-server/tests/integration/board-api.test.ts b/packages/board-server/tests/integration/board-api.test.ts deleted file mode 100644 index 3d43a2640d0..00000000000 --- a/packages/board-server/tests/integration/board-api.test.ts +++ /dev/null @@ -1,608 +0,0 @@ -import { suite, test } from "node:test"; -import assert from "node:assert"; -import { request } from "node:http"; -import { startServer, stopServer } from "../../src/server.js"; - -import fs from "fs"; -import path, { resolve } from "path"; - -import { fileURLToPath } from "url"; -import { dirname } from "path"; - -import { createAccount } from "../../src/server/store.js"; - -let serverInstance: { server: any; port: string | number }; - -var account: { api_key: any; account?: string }; - -import { deepStrictEqual } from "assert"; - -const MODULE_PATH = dirname(fileURLToPath(import.meta.url)); -const ROOT_PATH = resolve(MODULE_PATH, "../../../"); - -test.before(async () => { - serverInstance = await startServer(ROOT_PATH); - account = await createAccount("test"); -}); - -test.after(async () => { - await stopServer(serverInstance.server); - console.log("Server stopped"); - process.exit(0); -}); - -process.on("uncaughtException", async (err) => { - console.error("Uncaught Exception:", err); - if (serverInstance) { - await stopServer(serverInstance.server); - } - process.exit(1); -}); - -process.on("unhandledRejection", async (reason) => { - console.error("Unhandled Rejection:", reason); - if (serverInstance) { - await stopServer(serverInstance.server); - } - process.exit(1); -}); - -function readBoard(name: string) { - // Get the directory name - const __filename = fileURLToPath(import.meta.url); - const __dirname = dirname(__filename); - const filePath = path.join(__dirname, `../boards/${name}`); - return JSON.parse(fs.readFileSync(filePath, "utf-8")); -} - -function makeRequest({ - path, - method = "GET", - body, - headers, -}: { - path: string; - method?: string; - body?: unknown; - headers: any; -}): Promise<{ statusCode: number; data: string }> { - return new Promise((resolve, reject) => { - const options = { - hostname: "localhost", - port: 3000, - path, - method, - headers: headers, - }; - - const req = request(options, (res) => { - let data = ""; - - // Log the request details - console.log(`${method} http://localhost:${options.port}${path}`); - if (body) { - console.log(`Request body: ${JSON.stringify(body, null, 2)}`); - } - - // Log response status - console.log(`Response status: ${res.statusCode}`); - - res.on("data", (chunk) => { - data += chunk; - }); - - res.on("end", () => { - resolve({ statusCode: res.statusCode || 500, data }); - }); - }); - - req.on("error", (err) => { - reject(err); - }); - - // If there's a body, write it to the request - if (body) { - req.write(JSON.stringify(body)); - } - - req.end(); - }); -} - -type ExpectedResult = { - type: string; - outputs?: Record; - path?: number[]; - from?: number[]; - to?: number[]; -}; - -const assertResults = ( - results: any[], - expectedResults: ExpectedResult[], - index = 0 -) => { - if (results.length !== expectedResults.length) { - assert.fail( - `Expected ${expectedResults.length} results, but got ${results.length} at index ${index}` - ); - } - for (const [i, result] of results.entries()) { - const expected = expectedResults[i]!; - const [type, data] = result; - if (type === "error") { - assert.fail(`Unexpected error: ${data}`); - } - assert.strictEqual( - type, - expected.type, - `Expected state type to be ${expected.type} at index ${index}` - ); - switch (type) { - case "output": { - deepStrictEqual( - data.outputs, - expected.outputs, - `Expected outputs to match at index ${index}` - ); - break; - } - case "edge": { - const { from, to } = data; - if (expected.from) { - deepStrictEqual( - from, - expected.from, - `Expected from "${JSON.stringify(from)}" to match "${JSON.stringify(expected.from)}" at index ${index}` - ); - } - if (expected.to) { - deepStrictEqual( - to, - expected.to, - `Expected to "${JSON.stringify(to)}" to match "${JSON.stringify(expected.to)}" at index ${index}` - ); - } - break; - } - case "graphstart": - case "graphend": - case "nodestart": - case "nodeend": { - deepStrictEqual( - data.path, - expected.path, - `Expected path "${JSON.stringify(data.path)}" to match "${JSON.stringify(expected.path)}" at index ${index}` - ); - break; - } - } - } -}; - -const scriptedRun = async ( - boardName: string, - script: { inputs?: Record; expected: ExpectedResult[] }[], - apiKey: string -) => { - let next; - for (const [index, { inputs, expected }] of script.entries()) { - const inputData = { - ...inputs, - $key: apiKey, - ...(next ? { $next: next } : {}), - }; - - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/${boardName}.api/run`, - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: inputData, - }); - - assert.strictEqual(statusCode, 200); - - const events = body - .split("\n\n") - .filter(Boolean) - .map((event) => { - const jsonStr = event.replace("data: ", ""); - return JSON.parse(jsonStr); - }); - - assertResults(events, expected, index); - next = getNext(events[events.length - 1]); - } -}; - -const getNext = (result?: any) => { - if (!result) { - throw new Error("No result provided."); - } - const [type, data, next] = result; - if (type === "error") { - throw new Error(data.error as string); - } - if (type === "input") { - return next; - } - if (type === "output" || type === "end") { - return undefined; - } - throw new Error(`Unexpected state type: ${type}`); -}; - -suite("Board API Integration tests", async () => { - test("GET /boards should list boards", { concurrency: false }, async () => { - const { statusCode, data: body } = await makeRequest({ - path: "/boards", - method: "GET", - headers: { "Content-Type": "application/json" }, - }); - assert.strictEqual(statusCode, 200); - }); - - test( - "POST /boards/@test/simple.json should create a new board", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.json?API_KEY=${account.api_key}`, - method: "POST", - body: readBoard("simple.bgl.json"), - headers: { "Content-Type": "application/json" }, - }); - assert.strictEqual(statusCode, 200); - assert.deepStrictEqual(JSON.parse(body), { - created: `@${account.account}/simple.json`, - }); - } - ); - - test( - "GET /boards/@test/simple.json should get a board", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.json`, - method: "GET", - headers: { "Content-Type": "application/json" }, - }); - assert.strictEqual(statusCode, 200); - assert.deepStrictEqual(JSON.parse(body), readBoard("simple.bgl.json")); - } - ); - - test( - "GET /boards should be empty while @test/simple.json is unpublished", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: "/boards", - method: "GET", - headers: { "Content-Type": "application/json" }, - }); - assert.strictEqual(statusCode, 200); - assert.deepStrictEqual(JSON.parse(body), []); - } - ); - - test( - "POST /boards/@test/simple.json should update a board", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.json?API_KEY=${account.api_key}`, - method: "POST", - body: readBoard("simple-published.bgl.json"), - headers: {}, - }); - assert.strictEqual(statusCode, 200); - assert.deepStrictEqual(JSON.parse(body), { - created: `@${account.account}/simple.json`, - }); - } - ); - - test( - "GET /boards/@test/simple.json should be published", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.json`, - method: "GET", - headers: {}, - }); - assert.strictEqual(statusCode, 200); - assert.deepStrictEqual( - JSON.parse(body), - readBoard("simple-published.bgl.json") - ); - } - ); - - test( - "GET /boards should list the published board", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: "/boards", - method: "GET", - headers: {}, - }); - assert.strictEqual(statusCode, 200); - assert.deepStrictEqual(JSON.parse(body), [ - { - title: "simple", - path: `${account.account}/simple.json`, - username: account.account, - readonly: true, - mine: false, - tags: "published", - }, - ]); - } - ); - - test( - "GET /boards/@test/simple.app should serve frontend app", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.app`, - method: "GET", - headers: {}, - }); - console.info(body); - assert.strictEqual(statusCode, 200); - } - ); - - test( - "GET /boards/@test/simple.api should serve API explorer", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.api`, - method: "GET", - headers: {}, - }); - assert.strictEqual(statusCode, 200); - assert(body.includes(" { - const inputData = { - text: "Hello, API!", - $key: account.api_key, - }; - - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.api/invoke`, - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: inputData, - }); - - assert.strictEqual(statusCode, 200); - - const response = JSON.parse(body); - - // Check if the response contains the expected output - assert(response.text, "Response should contain output"); - assert.strictEqual( - response.text, - "Hello, API!", - "Output should echo the input" - ); - } - ); - - test( - "POST /boards/@test/simple.api/describe should serve API description", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.api/describe`, - method: "POST", - headers: { "Content-Type": "application/json" }, - }); - - console.log("Describe response:", statusCode, body); - - assert.strictEqual(statusCode, 200); - - const response = JSON.parse(body); - - // Check if the response contains the expected properties - assert(response.title, "Response should contain a title"); - assert(response.inputSchema, "Response should contain an inputSchema"); - assert(response.outputSchema, "Response should contain an outputSchema"); - - // Check if the $key input has been added - assert( - response.inputSchema.properties.$key, - "InputSchema should contain a $key property" - ); - assert( - response.inputSchema.required.includes("$key"), - "InputSchema should require $key" - ); - - assert.strictEqual( - response.title, - "simple", - "Title should match the simple board" - ); - } - ); - - test( - "POST /boards/@test/simple.api/run should execute the board", - { concurrency: false }, - async () => { - const inputData = { - text: "Hello, API!", - $key: account.api_key, - }; - - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.api/run`, - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: inputData, - }); - - assert.strictEqual(statusCode, 200); - - // The response is a stream of events, so we need to parse each event - const events = body - .split("\n\n") - .filter(Boolean) - .map((event) => { - const jsonStr = event.replace("data: ", ""); - return JSON.parse(jsonStr); - }); - - // Check if there's at least one event - assert(events.length > 0, "Response should include at least one event"); - - // Check the final output - const outputEvent = events.find((event) => event[0] === "output"); - assert(outputEvent, "Response should include an output event"); - assert.deepStrictEqual( - outputEvent[1].outputs, - { text: "Hello, API!" }, - "Output should echo the input" - ); - } - ); - - test( - "GET /boards/@test/simple.invite should list invites", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.invite?API_KEY=${account.api_key}`, - method: "GET", - headers: { "Content-Type": "application/json" }, - }); - assert.strictEqual(statusCode, 200); - const response = JSON.parse(body); - assert( - Array.isArray(response.invites), - "Response should contain an array of invites" - ); - } - ); - - test( - "POST /boards/@test/simple.invite should create a new invite", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.invite?API_KEY=${account.api_key}`, - method: "POST", - headers: { "Content-Type": "application/json" }, - }); - assert.strictEqual(statusCode, 200); - const response = JSON.parse(body); - assert(response.invite, "Response should contain a new invite code"); - } - ); - - test( - "POST /boards/@test/simple.invite should delete an invite", - { concurrency: false }, - async () => { - // First, create an invite - const { data: createBody } = await makeRequest({ - path: `/boards/@${account.account}/simple.invite?API_KEY=${account.api_key}`, - method: "POST", - headers: { "Content-Type": "application/json" }, - }); - const createResponse = JSON.parse(createBody); - const inviteToDelete = createResponse.invite; - - // Now, delete the invite - const { statusCode, data: deleteBody } = await makeRequest({ - path: `/boards/@${account.account}/simple.invite?API_KEY=${account.api_key}`, - method: "POST", - headers: { "Content-Type": "application/json" }, - body: { delete: inviteToDelete }, - }); - assert.strictEqual(statusCode, 200); - const deleteResponse = JSON.parse(deleteBody); - assert.strictEqual( - deleteResponse.deleted, - inviteToDelete, - "Response should confirm the deleted invite" - ); - } - ); - - test( - "POST /boards/@test/simple.invite should fail to delete non-existent invite", - { concurrency: false }, - async () => { - const { statusCode, data: body } = await makeRequest({ - path: `/boards/@${account.account}/simple.invite?API_KEY=${account.api_key}`, - method: "POST", - headers: { "Content-Type": "application/json" }, - body: { delete: "non-existent-invite" }, - }); - assert.strictEqual(statusCode, 200); // The API currently returns 200 even for failures - const response = JSON.parse(body); - assert(response.error, "Response should contain an error message"); - } - ); - - test( - "POST and run a board with bubbling input", - { concurrency: false }, - async () => { - // First, create the new board - const newBoard = readBoard("invoke-board-with-bubbling-input.bgl.json"); - const createResponse = await makeRequest({ - path: `/boards/@${account.account}/invoke-board-with-bubbling-input.json?API_KEY=${account.api_key}`, - method: "POST", - body: newBoard, - headers: { "Content-Type": "application/json" }, - }); - assert.strictEqual(createResponse.statusCode, 200); - - // Now, run the board using scriptedRun - await scriptedRun( - "invoke-board-with-bubbling-input", - [ - { - inputs: { name: "Alice" }, - expected: [{ type: "input" }], - }, - { - inputs: { location: "Wonderland" }, - expected: [ - { - type: "output", - outputs: { - greeting: 'Greeting is: "Hello, Alice from Wonderland!"', - }, - }, - ], - }, - ], - account.api_key - ); - } - ); -}); diff --git a/packages/board-server/tests/invoke-board.ts b/packages/board-server/tests/invoke-board.ts deleted file mode 100644 index 49a1c4cdf98..00000000000 --- a/packages/board-server/tests/invoke-board.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { deepStrictEqual } from "assert"; -import type { Kit } from "@google-labs/breadboard"; - -import simpleBoard from "./boards/simple.bgl.json" with { type: "json" }; -import { invokeBoard } from "../src/server/boards/utils/invoke-board.js"; - -const mockSecretsKit: Kit = { - url: import.meta.url, - handlers: { - secrets: async (inputs) => { - throw new Error("Secrets aren't implemented in tests."); - }, - }, -}; - -describe("Board Server Invokes Boards", () => { - test("can invoke a simple board", async () => { - const path = "/path/to/board"; - const inputs = { text: "bar" }; - const result = await invokeBoard({ - path, - url: `https://example.com${path}`, - inputs, - loader: async () => simpleBoard, - }); - deepStrictEqual(result, { text: "bar" }); - }); -}); diff --git a/packages/board-server/tests/parser-data.json b/packages/board-server/tests/parser-data.json deleted file mode 100644 index e385973067d..00000000000 --- a/packages/board-server/tests/parser-data.json +++ /dev/null @@ -1,148 +0,0 @@ -[ - { - "url": "https://example.com/boards", - "method": "GET", - "result": { "success": true, "type": "list" } - }, - { - "url": "https://example.com/boards", - "method": "POST", - "result": { "success": true, "type": "create" } - }, - { - "url": "https://example.com/beards", - "method": "GET", - "result": { "success": false, "code": 404, "error": "Not found" } - }, - { - "url": "https://example.com/boards/foo", - "method": "GET", - "result": { "success": false, "code": 404, "error": "Not found" } - }, - { - "url": "https://example.com/boards/@user", - "method": "GET", - "result": { "success": false, "code": 404, "error": "Not found" } - }, - { - "url": "https://example.com/boards/@user/name.json", - "method": "GET", - "result": { - "success": true, - "type": "get", - "board": "@user/name.json", - "name": "name.json", - "user": "user", - "url": "https://example.com/boards/@user/name.json" - } - }, - { - "url": "https://example.com/boards/@user/name.json", - "method": "POST", - "result": { - "success": true, - "type": "update", - "board": "@user/name.json", - "name": "name.json", - "user": "user", - "url": "https://example.com/boards/@user/name.json" - } - }, - { - "url": "https://example.com/boards/@user/name.js", - "method": "GET", - "result": { "success": false, "code": 404, "error": "Not found" } - }, - { - "url": "https://example.com/boards/@user/name.json/invoke", - "method": "GET", - "result": { "success": false, "code": 404, "error": "Not found" } - }, - { - "url": "https://example.com/boards/@user/name.api/invoke", - "method": "GET", - "result": { "success": false, "code": 405, "error": "Invalid method" } - }, - { - "url": "https://example.com/boards/@user/name.api/invoke", - "method": "POST", - "result": { - "success": true, - "type": "invoke", - "board": "@user/name.json", - "name": "name.json", - "user": "user", - "url": "https://example.com/boards/@user/name.json" - } - }, - { - "url": "https://example.com/boards/@user/name.api/invoke?API_KEY=foo", - "method": "POST", - "result": { - "success": true, - "type": "invoke", - "board": "@user/name.json", - "name": "name.json", - "user": "user", - "url": "https://example.com/boards/@user/name.json" - } - }, - { - "url": "https://example.com/boards/@user/name.api/describe", - "method": "GET", - "result": { "success": false, "code": 405, "error": "Invalid method" } - }, - { - "url": "https://example.com/boards/@user/name.api/describe", - "method": "POST", - "result": { - "success": true, - "type": "describe", - "board": "@user/name.json", - "name": "name.json", - "user": "user", - "url": "https://example.com/boards/@user/name.json" - } - }, - { - "url": "https://example.com/boards/@user/name.api/run", - "method": "POST", - "result": { - "success": true, - "type": "run", - "board": "@user/name.json", - "name": "name.json", - "user": "user", - "url": "https://example.com/boards/@user/name.json" - } - }, - { - "url": "https://example.com/boards/@user/name.app/describe", - "method": "GET", - "result": { "success": false, "code": 404, "error": "Not found" } - }, - { - "url": "https://example.com/boards/@user/name.api", - "method": "GET", - "result": { - "success": true, - "type": "api", - "board": "@user/name.json", - "name": "name.json", - "user": "user", - "url": "https://example.com/boards/@user/name.json" - } - }, - { - "url": "https://example.com/boards/@user/name.app", - "method": "GET", - "result": { - "success": true, - "type": "app", - "board": "@user/name.json", - "name": "name.json", - "user": "user", - "url": "https://example.com/boards/@user/name.json" - } - } -] diff --git a/packages/board-server/tests/run-board.ts b/packages/board-server/tests/run-board.ts deleted file mode 100644 index c53cd9c8ca3..00000000000 --- a/packages/board-server/tests/run-board.ts +++ /dev/null @@ -1,410 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { deepStrictEqual, fail } from "assert"; -import { runBoard } from "../src/server/boards/utils/run-board.js"; -import type { - GraphDescriptor, - Kit, - OutputValues, - ReanimationState, -} from "@google-labs/breadboard"; - -import simpleBoard from "./boards/simple.bgl.json" with { type: "json" }; -import multipleInputsBoard from "./boards/many-inputs.bgl.json" with { type: "json" }; -import manyOutputsBoard from "./boards/many-outputs.bgl.json" with { type: "json" }; -import invokeWithBubblingInput from "./boards/invoke-board-with-bubbling-input.bgl.json" with { type: "json" }; -import type { RemoteMessage } from "@google-labs/breadboard/remote"; -import type { RunDiagnosticsLevel } from "@google-labs/breadboard/harness"; -import type { RunBoardStateStore } from "../src/server/types.js"; - -const mockSecretsKit: Kit = { - url: import.meta.url, - handlers: { - secrets: async () => { - throw new Error("Secrets aren't implemented in tests."); - }, - }, -}; - -const assertResults = ( - results: RemoteMessage[], - expectedResults: ExpectedResult[], - index = 0 -) => { - if (results.length !== expectedResults.length) { - fail( - `Expected ${expectedResults.length} results, but got ${results.length} at index ${index}` - ); - } - for (const [i, result] of results.entries()) { - const expected = expectedResults[i]!; - const [type, data] = result; - if (type === "error") { - fail(`Unexpected error: ${data}`); - } - deepStrictEqual( - type, - expected.type, - `Expected state type to be ${expected.type} at index ${index}` - ); - switch (type) { - case "output": { - deepStrictEqual( - data.outputs, - expected.outputs, - `Expected outputs to match at index ${index}` - ); - break; - } - case "edge": { - const [, data] = result; - const { from, to } = data; - if (expected.from) { - deepStrictEqual( - from, - expected.from, - `Expected from "${JSON.stringify(from)}" to match "${JSON.stringify(expected.from)}" at index ${index}` - ); - } - if (expected.to) { - deepStrictEqual( - to, - expected.to, - `Expected to "${JSON.stringify(to)}" to match "${JSON.stringify(expected.to)}" at index ${index}` - ); - } - break; - } - case "graphstart": - case "graphend": - case "nodestart": - case "nodeend": { - const [, data] = result; - deepStrictEqual( - data.path, - expected.path, - `Expected path "${JSON.stringify(data.path)}" to match "${JSON.stringify(expected.path)}" at index ${index}` - ); - break; - } - } - } -}; - -const getNext = (result?: RemoteMessage) => { - if (!result) { - fail("No result provided."); - } - const [type, data, next] = result; - if (type === "error") { - fail(data.error as string); - } - if (type === "input") { - return next; - } - if (type === "output") { - return undefined; - } - if (type === "end") { - return undefined; - } - fail(`Unexpected state type: ${type}`); -}; - -type ExpectedResult = { - type: string; - outputs?: OutputValues; - path?: number[]; - from?: number[]; - to?: number[]; -}; - -type RunScriptEntry = { - inputs?: Record; - expected: ExpectedResult[]; -}; - -const runStateStore: RunBoardStateStore = { - async loadReanimationState(user: string, ticket: string) { - const state = JSON.parse(ticket) as ReanimationState; - if (!state.states) { - return undefined; - } - return state; - }, - async saveReanimationState(user: string, state: any) { - return JSON.stringify(state); - }, -}; - -const scriptedRun = async ( - board: GraphDescriptor, - script: RunScriptEntry[], - diagnostics: RunDiagnosticsLevel = false -) => { - let next; - const path = "/path/to/board"; - for (const [index, { inputs, expected }] of script.entries()) { - const results: RemoteMessage[] = []; - const writer = new WritableStream({ - async write(chunk) { - results.push(chunk); - }, - }).getWriter(); - - await runBoard({ - user: "test", - path, - url: `https://example.com${path}`, - loader: async () => board, - inputs, - next, - writer, - runStateStore, - diagnostics, - }); - assertResults(results, expected, index); - next = getNext(results[results.length - 1]); - } -}; - -describe("Board Server Runs Boards", () => { - test("can start a simple board", async () => { - const path = "/path/to/board"; - const results: RemoteMessage[] = []; - const writer = new WritableStream({ - async write(chunk) { - results.push(chunk); - }, - }).getWriter(); - await runBoard({ - user: "test", - path, - url: `https://example.com${path}`, - loader: async () => simpleBoard, - writer, - runStateStore, - }); - assertResults(results, [{ type: "input" }]); - }); - - test("can finish a simple board", async () => { - await scriptedRun(simpleBoard, [ - { expected: [{ type: "input" }] }, - { - inputs: { text: "foo" }, - expected: [{ type: "output", outputs: { text: "foo" } }], - }, - ]); - }); - - test("can start a simple board with inputs", async () => { - const path = "/path/to/board"; - const inputs = { text: "bar" }; - const results: RemoteMessage[] = []; - const writer = new WritableStream({ - async write(chunk) { - results.push(chunk); - }, - }).getWriter(); - await runBoard({ - user: "test", - path, - url: `https://example.com${path}`, - inputs, - loader: async () => simpleBoard, - writer, - runStateStore, - }); - assertResults(results, [ - { - type: "output", - outputs: { - text: "bar", - }, - }, - ]); - }); - - test("can start a board with multiple inputs", async () => { - const path = "/path/to/board"; - const inputs = { text: "bar", number: 42 }; - const results: RemoteMessage[] = []; - const writer = new WritableStream({ - async write(chunk) { - results.push(chunk); - }, - }).getWriter(); - await runBoard({ - user: "test", - path, - url: `https://example.com${path}`, - inputs, - loader: async () => multipleInputsBoard as GraphDescriptor, - writer, - runStateStore, - }); - assertResults(results, [{ type: "input" }]); - }); - - test("can finish a board with multiple inputs", async () => { - await scriptedRun(multipleInputsBoard as GraphDescriptor, [ - { expected: [{ type: "input" }] }, - { inputs: { text1: "foo" }, expected: [{ type: "input" }] }, - { - inputs: { text2: "bar" }, - expected: [ - { - type: "output", - outputs: { - "text-one": "foo", - "text-two": "bar", - }, - }, - ], - }, - ]); - }); - - test("can finish a board with multiple outputs", async () => { - await scriptedRun(manyOutputsBoard as GraphDescriptor, [ - { expected: [{ type: "input" }] }, - { - inputs: { start: "foo" }, - expected: [ - { - type: "output", - outputs: { one: "foo" }, - }, - { - type: "output", - outputs: { two: "foo" }, - }, - ], - }, - ]); - }); - - test("can finish a board with bubbling inputs", async () => { - await scriptedRun(invokeWithBubblingInput as GraphDescriptor, [ - { expected: [{ type: "input" }] }, - { inputs: { name: "Bob" }, expected: [{ type: "input" }] }, - { - inputs: { location: "New York" }, - expected: [ - { - type: "output", - outputs: { - greeting: 'Greeting is: "Hello, Bob from New York!"', - }, - }, - ], - }, - ]); - }); - - test("can finish a board with bubbling inputs with diagnostics", async () => { - await scriptedRun( - invokeWithBubblingInput as GraphDescriptor, - [ - { - expected: [ - { type: "graphstart", path: [] }, - { type: "edge", from: undefined, to: [1] }, - { type: "nodestart", path: [1] }, - { type: "input" }, - ], - }, - { - inputs: { name: "Bob" }, - expected: [ - { type: "nodeend", path: [1] }, - { type: "edge", from: [1], to: [2] }, - { type: "nodestart", path: [2] }, - { type: "graphstart", path: [2] }, - { type: "edge", from: undefined, to: [2, 1] }, - { type: "nodestart", path: [2, 1] }, - { type: "input" }, - ], - }, - { - inputs: { location: "New York" }, - expected: [ - { type: "nodeend", path: [2, 1] }, - { type: "edge", from: [2, 1], to: [2, 2] }, - { type: "nodestart", path: [2, 2] }, - { type: "nodeend", path: [2, 2] }, - { type: "edge", from: [2, 1], to: [2, 3] }, - { type: "edge", from: [2, 2], to: [2, 4] }, - { type: "nodestart", path: [2, 4] }, - { type: "nodeend", path: [2, 4] }, - { type: "graphend", path: [2] }, - { type: "nodeend", path: [2] }, - { type: "edge", from: [2], to: [3] }, - { type: "nodestart", path: [3] }, - { type: "nodeend", path: [3] }, - { type: "edge", from: [3], to: [4] }, - { type: "nodestart", path: [4] }, - { - type: "output", - outputs: { - greeting: 'Greeting is: "Hello, Bob from New York!"', - }, - }, - { type: "nodeend", path: [4] }, - { type: "graphend", path: [] }, - { type: "end" }, - ], - }, - ], - true - ); - }); - - test('can finish a board with bubbling inputs with "top" diagnostics', async () => { - await scriptedRun( - invokeWithBubblingInput as GraphDescriptor, - [ - { - expected: [ - { type: "graphstart", path: [] }, - { type: "nodestart", path: [1] }, - { type: "input" }, - ], - }, - { - inputs: { name: "Bob" }, - expected: [ - { type: "nodeend", path: [1] }, - { type: "nodestart", path: [2] }, - { type: "input" }, - ], - }, - { - inputs: { location: "New York" }, - expected: [ - { type: "nodeend", path: [2] }, - { type: "nodestart", path: [3] }, - { type: "nodeend", path: [3] }, - { type: "nodestart", path: [4] }, - { - type: "output", - outputs: { - greeting: 'Greeting is: "Hello, Bob from New York!"', - }, - }, - { type: "nodeend", path: [4] }, - { type: "graphend", path: [] }, - { type: "end" }, - ], - }, - ], - "top" - ); - }); -}); diff --git a/packages/board-server/tsconfig.json b/packages/board-server/tsconfig.json deleted file mode 100644 index a0bb83789ce..00000000000 --- a/packages/board-server/tsconfig.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "compilerOptions": { - "outDir": "dist", - "tsBuildInfoFile": "dist/.tsbuildinfo", - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "types": ["node"], - "lib": ["ES2022", "DOM"], - "incremental": true, - "declaration": true, - "sourceMap": true, - "inlineSources": true, - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedIndexedAccess": true, - "verbatimModuleSyntax": true, - "useUnknownInCatchVariables": true, - "experimentalDecorators": true, - "useDefineForClassFields": false, - "resolveJsonModule": true, - "esModuleInterop": true - }, - "include": ["src/**/*.ts", "tests/**/*.ts", "tests/**/*.json"], - "exclude": [] -} diff --git a/packages/board-server/vite.config.ts b/packages/board-server/vite.config.ts deleted file mode 100644 index 4a540dc010b..00000000000 --- a/packages/board-server/vite.config.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { defineConfig } from "vite"; - -export default defineConfig({ - optimizeDeps: { esbuildOptions: { target: "esnext" } }, - build: { - target: "esnext", - outDir: "./dist/client", - lib: { - entry: { - index: "./index.html", - api: "./api.html", - oauth: "./oauth/index.html", - }, - formats: ["es"], - }, - }, - resolve: { - dedupe: ["lit"], - }, -}); diff --git a/packages/breadboard-cli/.eslintrc b/packages/breadboard-cli/.eslintrc deleted file mode 100644 index 6a5f40d67cd..00000000000 --- a/packages/breadboard-cli/.eslintrc +++ /dev/null @@ -1,16 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, - "overrides": [ - { - "files": ["!./vite.config.ts"], - "parserOptions": { - "project": false, - }, - "rules": { - "expect-type/expect": "off", - }, - }, - ], -} diff --git a/packages/breadboard-cli/.gitignore b/packages/breadboard-cli/.gitignore deleted file mode 100644 index a6d7ecd9ea8..00000000000 --- a/packages/breadboard-cli/.gitignore +++ /dev/null @@ -1 +0,0 @@ -temp/ diff --git a/packages/breadboard-cli/CHANGELOG.md b/packages/breadboard-cli/CHANGELOG.md deleted file mode 100644 index 029c97c5914..00000000000 --- a/packages/breadboard-cli/CHANGELOG.md +++ /dev/null @@ -1,984 +0,0 @@ -# @google-labs/breadboard-cli - -## 0.11.2 - -### Patch Changes - -- Updated dependencies [49e2740] -- Updated dependencies [ab92d99] -- Updated dependencies [54c8197] -- Updated dependencies [703f17d] -- Updated dependencies [4e620ed] -- Updated dependencies [bc967e3] -- Updated dependencies [a74db56] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [981bd9e] -- Updated dependencies [226be62] -- Updated dependencies [5bf9e8d] -- Updated dependencies [8f9fddf] -- Updated dependencies [2fa05f0] -- Updated dependencies [fd69479] -- Updated dependencies [508c4b3] -- Updated dependencies [033d656] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [f71bcfb] -- Updated dependencies [24dd1d1] -- Updated dependencies [a104fa7] -- Updated dependencies [12cdec3] -- Updated dependencies [9a9f5c2] -- Updated dependencies [65c0449] -- Updated dependencies [8a1b8c4] -- Updated dependencies [f10e709] -- Updated dependencies [3188607] -- Updated dependencies [1f11bf3] -- Updated dependencies [4e00d85] -- Updated dependencies [9797718] -- Updated dependencies [4f4f3ee] -- Updated dependencies [d22e974] -- Updated dependencies [88298d5] -- Updated dependencies [9c878e2] -- Updated dependencies [2f68f71] -- Updated dependencies [b673bfa] -- Updated dependencies [8540b93] -- Updated dependencies [9254424] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3e68ec2] -- Updated dependencies [08d24da] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [feeed7a] -- Updated dependencies [4cc71ee] -- Updated dependencies [8330f0c] -- Updated dependencies [5990fd0] -- Updated dependencies [d0f99b4] -- Updated dependencies [a039d2e] -- Updated dependencies [b6eeb3e] -- Updated dependencies [e63b5dd] -- Updated dependencies [d99292e] -- Updated dependencies [1423647] -- Updated dependencies [392d7cd] -- Updated dependencies [e723c09] -- Updated dependencies [9783ba8] -- Updated dependencies [edefaf9] -- Updated dependencies [9fe7d4f] -- Updated dependencies [8c73da3] -- Updated dependencies [8572be4] -- Updated dependencies [df9b158] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [eb83b66] -- Updated dependencies [7fdf9c2] -- Updated dependencies [aafec7f] -- Updated dependencies [955ace6] -- Updated dependencies [cc72dcc] -- Updated dependencies [320c4c0] -- Updated dependencies [1ad3001] -- Updated dependencies [91fe8bb] -- Updated dependencies [7c2bf58] -- Updated dependencies [100fc95] -- Updated dependencies [4423c35] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [08ae0f6] -- Updated dependencies [1956396] -- Updated dependencies [a049abf] -- Updated dependencies [ec55e54] -- Updated dependencies [5834c81] -- Updated dependencies [d7606d3] -- Updated dependencies [77d9497] -- Updated dependencies [356897c] -- Updated dependencies [cac51cb] -- Updated dependencies [0ef793f] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] -- Updated dependencies [9c04caa] -- Updated dependencies [e026112] -- Updated dependencies [0088ede] -- Updated dependencies [60349b8] -- Updated dependencies [94759f7] -- Updated dependencies [40988de] -- Updated dependencies [d0e894d] - - @breadboard-ai/build@0.10.0 - - @breadboard-ai/visual-editor@1.19.0 - - @google-labs/core-kit@0.15.0 - - @google-labs/breadboard@0.27.0 - - @google-labs/template-kit@0.3.10 - - @breadboard-ai/import@0.1.10 - -## 0.11.1 - -### Patch Changes - -- Updated dependencies [3b9229d] -- Updated dependencies [bbcdd2d] -- Updated dependencies [fa8a752] -- Updated dependencies [9ed58cf] -- Updated dependencies [7f2ef33] -- Updated dependencies [85fb144] -- Updated dependencies [c1dc2a4] -- Updated dependencies [7d46a63] -- Updated dependencies [1a70e7d] -- Updated dependencies [bac2e35] -- Updated dependencies [ec2fedd] - - @breadboard-ai/visual-editor@1.18.0 - - @breadboard-ai/build@0.9.1 - - @google-labs/core-kit@0.14.1 - - @google-labs/breadboard@0.26.0 - - @breadboard-ai/import@0.1.9 - - @google-labs/template-kit@0.3.9 - -## 0.11.0 - -### Minor Changes - -- 7de241c: Remove `BoardRunner`. - -### Patch Changes - -- 49b3612: Restore preview functionality -- Updated dependencies [cc5f4b6] -- Updated dependencies [cacd8e2] -- Updated dependencies [1a6a9cf] -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [f6c6378] -- Updated dependencies [068e8cb] -- Updated dependencies [78a6bcf] -- Updated dependencies [df6ba88] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [a940b87] -- Updated dependencies [efdb201] -- Updated dependencies [b201e07] -- Updated dependencies [05e3ff2] -- Updated dependencies [15b5659] -- Updated dependencies [374ea85] -- Updated dependencies [0296c89] -- Updated dependencies [de90fb7] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [f93ec06] -- Updated dependencies [e0d5971] -- Updated dependencies [5f7f44b] -- Updated dependencies [cc5f4b6] -- Updated dependencies [398bf4f] -- Updated dependencies [28895c3] -- Updated dependencies [494d5ca] -- Updated dependencies [7de241c] -- Updated dependencies [c1e21f7] -- Updated dependencies [a424c92] -- Updated dependencies [ee1f9ca] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] -- Updated dependencies [9998938] - - @breadboard-ai/build@0.9.0 - - @breadboard-ai/visual-editor@1.17.0 - - @google-labs/breadboard@0.25.0 - - @google-labs/core-kit@0.14.0 - - @google-labs/template-kit@0.3.8 - - @breadboard-ai/import@0.1.8 - -## 0.10.2 - -### Patch Changes - -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [00875af] -- Updated dependencies [1dc645a] -- Updated dependencies [89ccc90] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [9f33a12] -- Updated dependencies [c04cff0] -- Updated dependencies [d88c37b] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - - @breadboard-ai/visual-editor@1.15.0 - - @google-labs/core-kit@0.13.0 - - @breadboard-ai/build@0.8.1 - - @breadboard-ai/import@0.1.7 - - @google-labs/template-kit@0.3.7 - -## 0.10.1 - -### Patch Changes - -- 9a2ffab: Unpin @breadboard-ai/build dependency from being overly constrained -- Updated dependencies [ad8aa22] -- Updated dependencies [e6c7269] -- Updated dependencies [62e5a34] -- Updated dependencies [bdaaa81] -- Updated dependencies [1e1be2a] -- Updated dependencies [6d2939e] -- Updated dependencies [fa9073d] -- Updated dependencies [15b6171] -- Updated dependencies [5c5b665] -- Updated dependencies [9171352] -- Updated dependencies [2b094a3] -- Updated dependencies [4e2fbd6] -- Updated dependencies [ec06605] -- Updated dependencies [fa93c3f] -- Updated dependencies [8d2e618] -- Updated dependencies [f78ec0a] -- Updated dependencies [215bd15] -- Updated dependencies [2a206e8] -- Updated dependencies [2b9ef5b] -- Updated dependencies [645eb63] -- Updated dependencies [a0852df] -- Updated dependencies [1a83a77] -- Updated dependencies [8b370d7] -- Updated dependencies [7298a47] -- Updated dependencies [ea7e2a1] -- Updated dependencies [8edcbc0] -- Updated dependencies [5f6d97c] -- Updated dependencies [98f0ff2] -- Updated dependencies [9a2ffab] -- Updated dependencies [0a846ff] -- Updated dependencies [618e265] -- Updated dependencies [a527740] -- Updated dependencies [b99472b] -- Updated dependencies [4bfaec5] -- Updated dependencies [f1546f5] -- Updated dependencies [2312443] -- Updated dependencies [960922e] -- Updated dependencies [1d98374] -- Updated dependencies [70ba2d3] -- Updated dependencies [b76f9a1] -- Updated dependencies [6ffa89c] -- Updated dependencies [15ae381] - - @breadboard-ai/build@0.8.0 - - @breadboard-ai/visual-editor@1.14.0 - - @google-labs/breadboard@0.23.0 - - @google-labs/core-kit@0.12.0 - - @google-labs/template-kit@0.3.6 - - @breadboard-ai/import@0.1.6 - -## 0.10.0 - -### Minor Changes - -- 6f82dea: Update Visual Editor package name -- 0f9d617: Move breadboard-web to visual-editor; remove breadbuddy -- 4ba1243: Migrate breadboard-ui to visual-editor - -### Patch Changes - -- f4397b9: Update remaining breadboard-web paths -- Updated dependencies [a925cf0] -- Updated dependencies [39f1aed] -- Updated dependencies [c77b034] -- Updated dependencies [43fc9fc] -- Updated dependencies [f4d2416] -- Updated dependencies [bc94299] -- Updated dependencies [6f82dea] -- Updated dependencies [f4397b9] -- Updated dependencies [166f290] -- Updated dependencies [66918fc] -- Updated dependencies [4c5bc52] -- Updated dependencies [da43bb5] -- Updated dependencies [5cf08f1] -- Updated dependencies [4bf8894] -- Updated dependencies [6b91b3e] -- Updated dependencies [eaca143] -- Updated dependencies [9d93cf8] -- Updated dependencies [54cb2d4] -- Updated dependencies [6a59c83] -- Updated dependencies [9d93cf8] -- Updated dependencies [e414ba0] -- Updated dependencies [b357fbc] -- Updated dependencies [0f9d617] -- Updated dependencies [bc8dcdd] -- Updated dependencies [ffbf163] -- Updated dependencies [8928fb7] -- Updated dependencies [fa2d1ab] -- Updated dependencies [51034a0] -- Updated dependencies [9d93cf8] -- Updated dependencies [7bdb5a2] -- Updated dependencies [cb455ef] -- Updated dependencies [d6706f2] -- Updated dependencies [10bfeba] -- Updated dependencies [d016297] -- Updated dependencies [ffe100b] -- Updated dependencies [5447426] -- Updated dependencies [bd55f95] -- Updated dependencies [cb0237d] -- Updated dependencies [4ba1243] -- Updated dependencies [05f3acb] -- Updated dependencies [9d4ea07] -- Updated dependencies [164d104] -- Updated dependencies [4c1a17c] -- Updated dependencies [26e1099] -- Updated dependencies [a0587ec] -- Updated dependencies [7e1f01c] -- Updated dependencies [359424b] -- Updated dependencies [a9def5c] -- Updated dependencies [a30fb39] - - @google-labs/breadboard@0.22.0 - - @breadboard-ai/visual-editor@1.12.0 - - @google-labs/core-kit@0.11.0 - - @breadboard-ai/build@0.7.1 - - @breadboard-ai/import@0.1.5 - - @google-labs/template-kit@0.3.5 - -## 0.9.5 - -### Patch Changes - -- 29774aa: Update dependency package versions. -- Updated dependencies [29774aa] - - @google-labs/breadboard-web@1.10.1 - - @google-labs/template-kit@0.3.4 - - @google-labs/core-kit@0.10.1 - -## 0.9.4 - -### Patch Changes - -- fea8967: Add basic "Save As..." support -- Updated dependencies [5a55b7d] -- Updated dependencies [f4c9d36] -- Updated dependencies [7dd8fee] -- Updated dependencies [74ade20] -- Updated dependencies [2e023b8] -- Updated dependencies [c27c176] -- Updated dependencies [59dd0f5] -- Updated dependencies [345738d] -- Updated dependencies [4e66406] -- Updated dependencies [417323c] -- Updated dependencies [3d5ae56] -- Updated dependencies [b3aa884] -- Updated dependencies [85bbc00] -- Updated dependencies [dfc6054] -- Updated dependencies [00825d5] -- Updated dependencies [57e8714] -- Updated dependencies [3d7b4a7] -- Updated dependencies [7af14cf] -- Updated dependencies [bcfba50] -- Updated dependencies [4db3ab7] -- Updated dependencies [d9b76bd] -- Updated dependencies [0a9769b] -- Updated dependencies [9c97650] -- Updated dependencies [608edac] -- Updated dependencies [5a55b7d] -- Updated dependencies [fea8967] -- Updated dependencies [631babd] -- Updated dependencies [778f7aa] -- Updated dependencies [808f5e2] -- Updated dependencies [d131307] -- Updated dependencies [499eac0] -- Updated dependencies [00746bb] -- Updated dependencies [726d38e] -- Updated dependencies [e0fdbc3] -- Updated dependencies [83ed3b5] -- Updated dependencies [54b03b9] -- Updated dependencies [810d7fd] -- Updated dependencies [14853d5] -- Updated dependencies [714a536] -- Updated dependencies [5a0afe4] -- Updated dependencies [8798514] -- Updated dependencies [eb64b9a] -- Updated dependencies [6fdd89e] -- Updated dependencies [cf17933] -- Updated dependencies [1f7e37d] -- Updated dependencies [bfa65a3] -- Updated dependencies [3ab7a87] -- Updated dependencies [431fa3d] -- Updated dependencies [ef86632] -- Updated dependencies [c82138d] -- Updated dependencies [8c90376] -- Updated dependencies [32a48a3] -- Updated dependencies [4db3ab7] -- Updated dependencies [cd73b17] -- Updated dependencies [81d82fe] -- Updated dependencies [537d9f9] -- Updated dependencies [2a7531b] -- Updated dependencies [8ec03e0] -- Updated dependencies [2e3f555] -- Updated dependencies [7c1b4cb] -- Updated dependencies [702cfe1] -- Updated dependencies [a5898df] -- Updated dependencies [bebd96e] -- Updated dependencies [91cb723] -- Updated dependencies [3e10f0f] -- Updated dependencies [0e54e55] -- Updated dependencies [c53ca01] -- Updated dependencies [6ada218] -- Updated dependencies [4c681cb] -- Updated dependencies [fb2e584] -- Updated dependencies [9491266] -- Updated dependencies [0e76614] -- Updated dependencies [2ace620] -- Updated dependencies [c5f8e4f] -- Updated dependencies [fcef799] -- Updated dependencies [08c999a] -- Updated dependencies [37418d9] -- Updated dependencies [26556b6] -- Updated dependencies [083f69c] -- Updated dependencies [5f09b1d] -- Updated dependencies [c03173d] -- Updated dependencies [b75a43e] -- Updated dependencies [d6867c0] -- Updated dependencies [6fdd89e] -- Updated dependencies [8dbb1cf] -- Updated dependencies [d1a9d8a] -- Updated dependencies [5b03d96] -- Updated dependencies [f0d8d67] -- Updated dependencies [9b1513a] -- Updated dependencies [510e198] -- Updated dependencies [836389d] -- Updated dependencies [225c7cc] -- Updated dependencies [546752d] -- Updated dependencies [009e0ea] -- Updated dependencies [9491266] -- Updated dependencies [7429050] -- Updated dependencies [06c3f57] -- Updated dependencies [331d4b5] - - @google-labs/breadboard-web@1.10.0 - - @google-labs/breadboard@0.21.0 - - @google-labs/core-kit@0.10.0 - - @breadboard-ai/build@0.7.0 - - @google-labs/template-kit@0.3.3 - - @breadboard-ai/import@0.1.4 - -## 0.9.3 - -### Patch Changes - -- a35406c: Add --format flag to make command which formats BGL in a deterministic way -- Updated dependencies [8097177] -- Updated dependencies [8774855] -- Updated dependencies [1b596d4] -- Updated dependencies [29eda71] -- Updated dependencies [4957dc5] -- Updated dependencies [fe4c564] -- Updated dependencies [4203076] -- Updated dependencies [7d0b89c] -- Updated dependencies [23b8acb] -- Updated dependencies [f60cb06] -- Updated dependencies [9212366] -- Updated dependencies [04e892e] -- Updated dependencies [cec6d54] -- Updated dependencies [e337629] -- Updated dependencies [c91fb1e] -- Updated dependencies [87eb8fe] -- Updated dependencies [69b6e44] -- Updated dependencies [f97a4d5] -- Updated dependencies [60a18c5] -- Updated dependencies [b0ed6f3] -- Updated dependencies [4957dc5] -- Updated dependencies [a209c51] -- Updated dependencies [3397974] -- Updated dependencies [7368fdd] -- Updated dependencies [c9c0e06] -- Updated dependencies [fe2066b] -- Updated dependencies [c1acf24] -- Updated dependencies [af54870] -- Updated dependencies [3920805] -- Updated dependencies [ab9a4ce] -- Updated dependencies [3b2bb4a] -- Updated dependencies [a35406c] -- Updated dependencies [31cf016] -- Updated dependencies [ab43276] -- Updated dependencies [477e6e6] -- Updated dependencies [cdcbcdb] -- Updated dependencies [cc1a625] -- Updated dependencies [ee85b67] -- Updated dependencies [791ec2a] -- Updated dependencies [c0293c9] -- Updated dependencies [1d29493] -- Updated dependencies [b6f5644] -- Updated dependencies [f870bdd] -- Updated dependencies [42495d8] -- Updated dependencies [a945fba] -- Updated dependencies [94caed3] -- Updated dependencies [43edef6] - - @google-labs/breadboard@0.20.0 - - @google-labs/core-kit@0.9.0 - - @breadboard-ai/build@0.6.0 - - @google-labs/breadboard-web@1.9.0 - - @breadboard-ai/import@0.1.3 - - @google-labs/template-kit@0.3.2 - -## 0.9.2 - -### Patch Changes - -- Updated dependencies [63eb779] - - @google-labs/breadboard@0.19.0 - - @google-labs/breadboard-web@1.8.1 - - @breadboard-ai/build@0.5.1 - - @google-labs/core-kit@0.8.1 - - @breadboard-ai/import@0.1.2 - - @google-labs/template-kit@0.3.1 - -## 0.9.1 - -### Patch Changes - -- Updated dependencies [dbd9267] -- Updated dependencies [3f9507d] -- Updated dependencies [39016d9] -- Updated dependencies [cef20ca] -- Updated dependencies [55a9647] -- Updated dependencies [1e86a87] -- Updated dependencies [3f9507d] -- Updated dependencies [18b9f34] -- Updated dependencies [1adb24c] -- Updated dependencies [1e86a87] -- Updated dependencies [d7829a1] -- Updated dependencies [fbf7a83] -- Updated dependencies [f03d11f] -- Updated dependencies [fefd109] -- Updated dependencies [c1dcb0a] -- Updated dependencies [54baba8] -- Updated dependencies [49c3aa1] -- Updated dependencies [cdc23bb] -- Updated dependencies [416aed2] -- Updated dependencies [1adb24c] -- Updated dependencies [fefd109] -- Updated dependencies [a1fcaea] -- Updated dependencies [1aa96c6] -- Updated dependencies [d9ac358] -- Updated dependencies [c3ed6a7] -- Updated dependencies [cc47fe7] -- Updated dependencies [f1883d1] -- Updated dependencies [1adb24c] -- Updated dependencies [d8cb0c9] -- Updated dependencies [e736f37] -- Updated dependencies [34d9c6d] -- Updated dependencies [34d9c6d] -- Updated dependencies [e6e0168] -- Updated dependencies [3d48482] -- Updated dependencies [24230c1] -- Updated dependencies [1adb24c] -- Updated dependencies [c117d4f] -- Updated dependencies [f2eda0b] -- Updated dependencies [5d601fb] -- Updated dependencies [3f9507d] -- Updated dependencies [626139b] -- Updated dependencies [1adb24c] -- Updated dependencies [3f9507d] -- Updated dependencies [bd44e29] -- Updated dependencies [c4ca6dc] -- Updated dependencies [1adb24c] -- Updated dependencies [6a2af3e] -- Updated dependencies [cfbcdf2] -- Updated dependencies [1d9cb16] -- Updated dependencies [ad5f570] -- Updated dependencies [49da151] -- Updated dependencies [43da00a] -- Updated dependencies [3f9507d] -- Updated dependencies [dfd5ce2] -- Updated dependencies [cfc0f15] -- Updated dependencies [00ccb9d] -- Updated dependencies [776f043] -- Updated dependencies [08eabf4] -- Updated dependencies [5369037] -- Updated dependencies [12b825f] -- Updated dependencies [c3587e1] -- Updated dependencies [34d9c6d] -- Updated dependencies [99fcffe] -- Updated dependencies [1e86a87] -- Updated dependencies [4d6ce42] -- Updated dependencies [3f9507d] -- Updated dependencies [d9ac358] - - @google-labs/breadboard-web@1.8.0 - - @breadboard-ai/build@0.5.0 - - @google-labs/breadboard@0.18.0 - - @google-labs/template-kit@0.3.0 - - @google-labs/core-kit@0.8.0 - - @breadboard-ai/import@0.1.1 - -## 0.9.0 - -### Minor Changes - -- 7e91ef0: CLI now uses OpenAPI import package - -### Patch Changes - -- be0a78e: Make settings work in debugger. -- Updated dependencies [b244fba] -- Updated dependencies [de524a4] -- Updated dependencies [c3cb25f] -- Updated dependencies [de524a4] -- Updated dependencies [ae79e4a] -- Updated dependencies [de524a4] -- Updated dependencies [276152e] -- Updated dependencies [72c5c6b] -- Updated dependencies [8046c47] -- Updated dependencies [de524a4] -- Updated dependencies [3a31595] -- Updated dependencies [634712b] -- Updated dependencies [a5543eb] -- Updated dependencies [0831735] -- Updated dependencies [dd810dd] -- Updated dependencies [c5ba396] -- Updated dependencies [7bafa40] -- Updated dependencies [2932f4b] -- Updated dependencies [51159c4] -- Updated dependencies [7e91ef0] -- Updated dependencies [5a7bc86] -- Updated dependencies [68c2ac4] -- Updated dependencies [6498389] -- Updated dependencies [6f9ba52] -- Updated dependencies [9a8bd0e] -- Updated dependencies [12c1a72] -- Updated dependencies [d60f38b] -- Updated dependencies [5602f1e] -- Updated dependencies [de524a4] - - @google-labs/template-kit@0.2.6 - - @breadboard-ai/build@0.4.0 - - @google-labs/breadboard@0.17.0 - - @google-labs/breadboard-web@1.7.0 - - @google-labs/core-kit@0.7.0 - - @breadboard-ai/import@0.1.0 - -## 0.8.2 - -### Patch Changes - -- Updated dependencies [0068682] -- Updated dependencies [ad9c233] -- Updated dependencies [65d869b] -- Updated dependencies [417cdf5] -- Updated dependencies [cf0ee4f] -- Updated dependencies [43cbed7] -- Updated dependencies [ff6433c] -- Updated dependencies [5382365] -- Updated dependencies [0e7f106] -- Updated dependencies [9ea6ba0] -- Updated dependencies [ffd2a6c] -- Updated dependencies [9d19852] -- Updated dependencies [324633d] - - @google-labs/breadboard-web@1.6.0 - - @google-labs/breadboard@0.16.0 - - @google-labs/core-kit@0.6.0 - - @breadboard-ai/build@0.3.1 - - @google-labs/template-kit@0.2.5 - -## 0.8.1 - -### Patch Changes - -- Updated dependencies [76da09d] -- Updated dependencies [938015d] -- Updated dependencies [182a546] -- Updated dependencies [4de92a3] - - @google-labs/breadboard-web@1.5.1 - - @google-labs/breadboard@0.15.0 - - @google-labs/core-kit@0.5.3 - - @breadboard-ai/build@0.3.0 - - @google-labs/template-kit@0.2.4 - -## 0.8.0 - -### Minor Changes - -- 261db21: Add CLI support for @breadboard-ai/build boards - -### Patch Changes - -- Updated dependencies [7949ec9] -- Updated dependencies [949bce7] -- Updated dependencies [e8d0737] -- Updated dependencies [da2e263] -- Updated dependencies [da2e263] - - @breadboard-ai/build@0.2.0 - - @google-labs/breadboard@0.14.0 - - @google-labs/breadboard-web@1.5.0 - - @google-labs/core-kit@0.5.2 - - @google-labs/template-kit@0.2.3 - -## 0.7.1 - -### Patch Changes - -- bdf14e1: Don't crash on TS errors in hot reload. - -## 0.7.0 - -### Minor Changes - -- 6d3c77c: Implement soft-reload - -### Patch Changes - -- edcf822: Avoid hard-coding `localhost` into a kit URL. -- Updated dependencies [05e74c9] -- Updated dependencies [faf1e12] -- Updated dependencies [51a38c0] -- Updated dependencies [8363d27] -- Updated dependencies [644c1ee] -- Updated dependencies [66128fa] -- Updated dependencies [d49b80e] -- Updated dependencies [9326bd7] -- Updated dependencies [5cd01a2] -- Updated dependencies [60f1754] -- Updated dependencies [fbad949] - - @google-labs/breadboard-web@1.4.0 - - @google-labs/breadboard@0.13.0 - - @google-labs/core-kit@0.5.1 - - @google-labs/template-kit@0.2.2 - -## 0.6.0 - -### Minor Changes - -- c3303a6: Adds --kit to `breadboard debug` -- b3beb36: Support loading kits via URL (both heavy and light kits) -- 3c497b0: Use esbuild.build to compile the boards. This enables importing modules. -- a8fc3f3: Teach `GraphProvider` to watch for file change notifications. - -### Patch Changes - -- decfa29: Introduce `DebuggerGraphProvider`. -- 6e631c4: Load agent-kit via manifest dynamically. -- c4f887b: Use simpler URLs in debugger. -- 2e3f0dc: Mark Node-specific packages as external -- 7ad0e2d: Updating `breadboard import` to use TypeScript and not board syntax. It changes the way boards work and can be called (no longer uses args) -- 1bbd16a: Start loading all heavy kits dynamically. -- b1fc53b: Teach `breadboard debug` to load PaLM Kit dynamically. -- Updated dependencies [f73c637] -- Updated dependencies [99446b8] -- Updated dependencies [866fc36] -- Updated dependencies [88b0f3a] -- Updated dependencies [a8bab08] -- Updated dependencies [a9e1849] -- Updated dependencies [699723b] -- Updated dependencies [decfa29] -- Updated dependencies [c3303a6] -- Updated dependencies [f005b3b] -- Updated dependencies [1f01afc] -- Updated dependencies [49c25aa] -- Updated dependencies [564f60c] -- Updated dependencies [6e631c4] -- Updated dependencies [c0d87f4] -- Updated dependencies [dcfdc37] -- Updated dependencies [d971aad] -- Updated dependencies [048e8ec] -- Updated dependencies [6143c58] -- Updated dependencies [dc35601] -- Updated dependencies [9cda2ff] -- Updated dependencies [60bd63c] -- Updated dependencies [be240b8] -- Updated dependencies [764ccda] -- Updated dependencies [b80a188] -- Updated dependencies [04d5420] -- Updated dependencies [56b90a4] -- Updated dependencies [1b48826] -- Updated dependencies [9a689c3] -- Updated dependencies [e648f64] -- Updated dependencies [dc648b1] -- Updated dependencies [628be93] -- Updated dependencies [ad5c1be] -- Updated dependencies [4a4a1f6] -- Updated dependencies [bac9bb1] -- Updated dependencies [ff4abd6] -- Updated dependencies [3e8cfcf] -- Updated dependencies [986af39] -- Updated dependencies [10f5110] -- Updated dependencies [3c497b0] -- Updated dependencies [3d536b6] -- Updated dependencies [eabd97b] -- Updated dependencies [14d5220] -- Updated dependencies [0bdff0b] -- Updated dependencies [6b5e96e] -- Updated dependencies [2008f69] -- Updated dependencies [1bbd16a] -- Updated dependencies [88372d9] -- Updated dependencies [c0f785a] -- Updated dependencies [a8fc3f3] -- Updated dependencies [32cfbaf] -- Updated dependencies [8dc4e00] -- Updated dependencies [6438930] -- Updated dependencies [5118c60] -- Updated dependencies [53df4e9] -- Updated dependencies [dd2cce6] -- Updated dependencies [cac4f4f] -- Updated dependencies [b1fc53b] -- Updated dependencies [ef05634] -- Updated dependencies [9f343a6] -- Updated dependencies [c208cfc] - - @google-labs/core-kit@0.5.0 - - @google-labs/breadboard-web@1.3.0 - - @google-labs/breadboard@0.12.0 - - @google-labs/template-kit@0.2.1 - -## 0.5.2 - -### Patch Changes - -- ff274a2: remove bundleDependencies - -## 0.5.1 - -### Patch Changes - -- Updated dependencies [07e66bf] -- Updated dependencies [26367fe] - - @google-labs/breadboard@0.11.2 - - @google-labs/core-kit@0.4.0 - - @google-labs/breadboard-web@1.2.2 - -## 0.5.0 - -### Minor Changes - -- f6e9b2c: Teach the Breadboard CLI how to use proxies - -### Patch Changes - -- 18a8089: Improves debug and make commands and how files are output -- f06f400: Remove temporary files created by TypeScript loader. -- Updated dependencies [c19513e] -- Updated dependencies [cd4f6e2] -- Updated dependencies [a9daeda] -- Updated dependencies [a4146c4] -- Updated dependencies [5221586] -- Updated dependencies [2237a4c] -- Updated dependencies [5cf1555] -- Updated dependencies [e6ed591] -- Updated dependencies [bd68ebd] -- Updated dependencies [9a76a87] -- Updated dependencies [0c2e494] -- Updated dependencies [ea652f3] -- Updated dependencies [56954c1] -- Updated dependencies [b944657] -- Updated dependencies [d378070] -- Updated dependencies [0085ee2] -- Updated dependencies [0ef9ec5] -- Updated dependencies [ee00249] -- Updated dependencies [c13513f] -- Updated dependencies [57e68ba] -- Updated dependencies [f06f400] -- Updated dependencies [56ccae5] -- Updated dependencies [4920d90] -- Updated dependencies [10a8129] -- Updated dependencies [c804ccc] -- Updated dependencies [5a65297] -- Updated dependencies [a4029de] -- Updated dependencies [53406ad] -- Updated dependencies [4c5b853] -- Updated dependencies [c3966d3] -- Updated dependencies [3f3f090] -- Updated dependencies [d7a7903] -- Updated dependencies [4401a98] -- Updated dependencies [f6e9b2c] - - @google-labs/breadboard@0.11.0 - - @google-labs/breadboard-web@1.2.0 - - @google-labs/core-kit@0.3.0 - - @google-labs/template-kit@0.2.0 - -## 0.4.1 - -### Patch Changes - -- 45654e1: update dependencies for running in a clean environment -- Updated dependencies [7dbc32e] - - @google-labs/breadboard-web@1.1.1 - -## 0.4.0 - -### Minor Changes - -- 9b55885: Fixing hosting directories in `breadboard debug` - -### Patch Changes - -- 7f9485b: Reenable cleanUrls for root -- d24932d: Catch compile/load errors to keep `breadboard debug` running. -- Updated dependencies [1b3f266] -- Updated dependencies [9bcd607] -- Updated dependencies [f6a7f43] - - @google-labs/breadboard-web@1.0.4 - - @google-labs/breadboard@0.10.0 - - @google-labs/core-kit@0.2.1 - - @google-labs/template-kit@0.1.3 - -## 0.3.2 - -### Patch Changes - -- d0b9b19: Fix a bug with file paths across Node releases. - -## 0.3.1 - -### Patch Changes - -- 3e9735e: Fix path resolution and stop serializing board URLs. - -## 0.3.0 - -### Minor Changes - -- d1f5299: Updating the import board - -### Patch Changes - -- b997fe4: Fix errors releating to missing dist/debugger files - -## 0.2.1 - -### Patch Changes - -- 1779e50: Add missing `vite` dependency. -- Updated dependencies [bbbd9f4] - - @google-labs/breadboard-web@1.0.3 - -## 0.2.0 - -### Minor Changes - -- 8eccdad: [breadboard-cli] Improvements to OpenAPI import to handle parameters as dynamic inputs and input config files - -### Patch Changes - -- 42a2b38: Updating the import board to dynamically resolve inputs for an API defined via OpenAPI -- Updated dependencies [67073c8] -- Updated dependencies [8eccdad] -- Updated dependencies [6e8c08d] -- Updated dependencies [3ab5892] -- Updated dependencies [780909c] -- Updated dependencies [bba68fd] -- Updated dependencies [6222fb3] -- Updated dependencies [58b623b] -- Updated dependencies [c89b67a] -- Updated dependencies [c71339f] -- Updated dependencies [b557794] -- Updated dependencies [a9206fc] -- Updated dependencies [605cff3] -- Updated dependencies [3356d08] -- Updated dependencies [931a95b] -- Updated dependencies [c89b67a] - - @google-labs/breadboard-web@1.0.0 - - @google-labs/breadboard@0.9.0 - - @google-labs/core-kit@0.2.0 - - @google-labs/template-kit@0.1.2 - -## 0.1.1 - -### Patch Changes - -- Updated dependencies [af00e58] - - @google-labs/breadboard@0.8.0 - - @google-labs/breadboard-web@0.0.2 - - @google-labs/core-kit@0.1.3 - - @google-labs/template-kit@0.1.1 diff --git a/packages/breadboard-cli/README.md b/packages/breadboard-cli/README.md deleted file mode 100644 index 541df9aa88f..00000000000 --- a/packages/breadboard-cli/README.md +++ /dev/null @@ -1,100 +0,0 @@ -# Breadboard CLI - -:note: The package is not yet published. You can use it by running `npx breadboard` from this monorepo. - -`npm install -g @google-labs/breadboard-cli` - -The CLI tools are designed to help you create and debug your breadboard files directly from your command line. - -## Usage - -### Debug - -`npx breadboard debug` - Brings up the web debug server -`npx breadboard debug ./tests/echo.json` - Brings up the local board hosted in the UI - -`npx breadboard debug ./tests/` - Brings up the local board hosted in the UI and show all the boards in the folder (and sub-folders). - -`npx breadboard debug ./tests/ --watch` - Brings up the local board hosted in the UI and show all the boards in the folder. If new boards added to the folder then they will be added to the UI and the UI will be automatically refreshed. - -`PORT=1234 npx breadboard debug` - Brings up the web debug server on port 1234 (the default port is -3000). - -Note: By default this command will convert any `ts` or `js` board files to `json` and save them along side the original file (this differs from other commands which will use the `-o` flag). If you do not want the boards to be saved, use the `--no-save` flag. - -### Import - -Imports an OpenAPI spec and converts the interface into a breadboard file that you can use. - -`npx breadboard import https://raw.githubusercontent.com/breadboard-ai/breadboard/c371c2cd5aca33673e30fc647c920228752e41ee/recipes/tools/openapi/tests/specs/openai.json -o ./` - Will import the latest `OpenAI` OpenAPI JSON spec and emit a breadboard file for each endpoint in the spec. - -or - -`npx breadboard import https://raw.githubusercontent.com/openai/openai-openapi/master/openapi.yaml -o ./` - Will import the latest `OpenAI` OpenAPI YAML spec and emit a breadboard file for each endpoint in the spec. - -`npx breadboard import https://raw.githubusercontent.com/breadboard-ai/breadboard/c371c2cd5aca33673e30fc647c920228752e41ee/recipes/tools/openapi/tests/specs/openai.json -a createEmbeddings` - Will import the latest `OpenAI` OpenAPI spec emit only the named endpoint (in this case `createEmbeddings`) - -If you don't specify an API (with `-a`), then you must specify the `-o` (output directory) flag because the tool will create a file for each endpoint in the spec. - -The `-o` flag will output to the filesystem and not the terminal. - -Note: The code for importing the OpenAPI spec is not complete - for example it doesn't handle all types of auth (currently only Bearer.) - -Now you can also do neat things such as ``npx breadboard import https://raw.githubusercontent.com/breadboard-ai/breadboard/c371c2cd5aca33673e30fc647c920228752e41ee/recipes/tools/openapi/tests/specs/openai.json -a createEmbeddings | npx breadboard mermaid` - -### Mermaid - -Creates a mermaid diagram from a breadboard file. - -Pass in a file: `npx breadboard mermaid packages/breadboard-cli/tests/echo.json` - -Pipe in a file: `npx breadboard mermaid < packages/breadboard-cli/tests/echo.json | npx breadboard mermaid` - -Pipe the output of a command: `cat packages/breadboard-cli/tests/echo.json | npx breadboard mermaid` - -Watching and piping the output of a command: `fswatch see/boards/rss.ts | xargs -n1 -I {} sh -c "npx breadboard mermaid {} -o ./ | mmdc -o test.png -i -"` - -### Make - -Creates a graph json from a breadboard javascript file: `npx breadboard make packages/breadboard-cli/boards/echo.js` - -`breadboard make [DIR]` - makes all the boards in dir/\*_/_ and outputs to cwd or `-o DIR` -`breadboard make [FILE]` - makes the file and outputs it to cwd or `-o DIR`` -`breadboard make [FILE] -n` - makes the file and outputs it to console. - -Pipe it to mermaid: `npx breadboard make packages/breadboard-cli/boards/echo.js -n | npx breadboard mermaid` - -Watch a directory and make the files: `fswatch see/boards/*.ts | xargs -n1 -I {} sh -c "npx breadboard make {} -o ./` - -### Run - -Creates a graph json from a breadboard javascript file. - -`npx breadboard run packages/breadboard-cli/boards/echo.js` - Runs the board and outputs the result to the console. Because there is no input defined, the board will ask you for input data. - -You can also pass in your own input with the `-i` flag: `npx breadboard run packages/breadboard-cli/boards/echo.js -i "{\"text\": \"Hello World\"}"`` - -If your board has kits, then you can pass in the kit name with the `--kit` flag (specify --kit for each kit you want to use) - -`npx breadboard run boards/news.json -i "{\"topic\": \"Paul Kinlan\"}" --kit "@google-labs/core-kit"` - -### Proxy - -`npx breadboard proxy` - Starts a proxy server that will allow your boards to defer some of their execution to this proxy server. This is useful for when you want to run a board that requires a secret or a token that you don't want to expose in the board file, or if the processing is too complex for the current host. - -`npx breadboard proxy --kit @google-labs/core-kit --proxy-node fetch --port 3000` - Starts a proxy server that will allow your boards to the `fetch` (as defined in `core-kit`) to defer some of their execution to this server. - -You can then run the board with `npx breadboard run`. For example to run the RSS fetch board you can run `npx breadboard run boards/components/fetch-rss/index.js --proxy http://localhost:3000/ --proxy-node fetch --kit=@google-labs/core-kit --kit @google-labs/json-kit`. This will run the board and defer the `fetch` node to the proxy server. - -#### Config file - -You can also use a config file to define the proxy server. The config file is a JSON file that looks like this: - -```json -{ - "kit": ["@google-labs/core-kit"], - "proxy": ["fetch"] -} -``` - -This also allows you to define more complex proxy nodes, such as Secrets tunnelling. diff --git a/packages/breadboard-cli/package.json b/packages/breadboard-cli/package.json deleted file mode 100644 index 0d94e3f8846..00000000000 --- a/packages/breadboard-cli/package.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "name": "@google-labs/breadboard-cli", - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "version": "0.11.2", - "description": "A suite of tools for interacting with the Breadboard.", - "bin": { - "breadboard": "dist/src/index.js" - }, - "main": "./dist/src/index.js", - "exports": "./dist/src/index.js", - "types": "dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "test": "wireit", - "build": "wireit", - "build:tsc": "wireit", - "build:debugger": "wireit", - "lint": "wireit", - "pack:install": "wireit", - "test:pack": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "../breadboard:build", - "build:tsc", - "build:debugger" - ] - }, - "build:debugger": { - "command": "vite build", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "../visual-editor:build:vite" - ], - "files": [ - "vite.config.ts", - "src/debugger/index.html", - "src/debugger/preview.html", - "src/debugger/provider.ts" - ], - "output": [ - "dist/debugger" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty && chmod +x dist/src/index.js", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "../breadboard:build:tsc", - "../visual-editor:build:tsc", - "../example-boards:build:tsc", - "../core-kit:build:tsc", - "../import:build", - "../template-kit:build:tsc" - ], - "files": [ - "src/**/*.js", - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "test": { - "command": "ava", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - }, - "pack:install": { - "command": "npm pack && npm --verbose install -g $(find . -name \"$(npm pkg get name | tr -d '\"' | sed 's/@//;s/\\//-/g').tgz\")", - "dependencies": [ - "build" - ], - "output": [ - "google-labs-breadboard-cli-*.tgz" - ] - }, - "test:pack": { - "command": "(cd ~ && npx --verbose @google-labs/breadboard-cli --help)", - "dependencies": [ - "pack:install" - ] - } - }, - "repository": { - "directory": "packages/breadboard-cli", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src", - "dist/ui", - "dist/debugger" - ], - "ava": { - "timeout": "30s", - "files": [ - "tests/**/*.ts" - ], - "workerThreads": false, - "typescript": { - "rewritePaths": { - "./": "dist/" - }, - "compile": false - } - }, - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/js-yaml": "^4.0.9", - "@types/node": "^22.0.0", - "@types/serve-handler": "^6.1.4", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "openapi-types": "^12.1.3", - "typescript": "^5.6.2" - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/import": "0.1.10", - "@breadboard-ai/visual-editor": "^1.19.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/template-kit": "^0.3.10", - "@rollup/plugin-commonjs": "^28.0.0", - "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@rollup/plugin-virtual": "^3.0.2", - "commander": "^12.1.0", - "esbuild": "^0.24.0", - "rollup": "^4.22.4", - "serve": "^14.2.3", - "urlpattern-polyfill": "^10.0.0", - "vite": "^5.4.8", - "yaml": "^2.5.1" - } -} diff --git a/packages/breadboard-cli/src/bundle/index.html b/packages/breadboard-cli/src/bundle/index.html deleted file mode 100644 index 7ff1fc85831..00000000000 --- a/packages/breadboard-cli/src/bundle/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - Breadboard - - - - - - - - - diff --git a/packages/breadboard-cli/src/bundle/worker.ts b/packages/breadboard-cli/src/bundle/worker.ts deleted file mode 100644 index 9839c155434..00000000000 --- a/packages/breadboard-cli/src/bundle/worker.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { serve } from "@google-labs/breadboard/harness"; -import { createServeConfig } from "@breadboard-ai/visual-editor/config.js"; - -serve(createServeConfig()); diff --git a/packages/breadboard-cli/src/commands/bundle.ts b/packages/breadboard-cli/src/commands/bundle.ts deleted file mode 100644 index 36b1775de76..00000000000 --- a/packages/breadboard-cli/src/commands/bundle.ts +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { build } from "vite"; -import { fileURLToPath } from "url"; -import path from "path"; -import fs from "fs/promises"; -import readline from "readline/promises"; - -export async function bundle(board: string, flags: { output: string }) { - let breadboardWebPublic; - if (typeof import.meta.resolve === "function") { - const publicPath = await import.meta.resolve( - "@breadboard-ai/visual-editor/public" - ); - breadboardWebPublic = fileURLToPath(publicPath); - } - - if (!breadboardWebPublic) { - console.error("Unable to locate Breadboard files"); - process.exit(1); - } - - const dirName = fileURLToPath(import.meta.url); - const bundleDir = path.join(dirName, "..", "..", "..", "..", "src", "bundle"); - - if (!path.isAbsolute(flags.output)) { - flags.output = path.join(process.cwd(), flags.output); - } - - if (!path.isAbsolute(board)) { - board = path.join(process.cwd(), board); - } - - const query = readline.createInterface({ - input: process.stdin, - output: process.stdout, - }); - - const answer = await query.question(`Write to ${flags.output}? Y/n: `); - if (!(answer === "" || answer === "Y" || answer == "y")) { - process.exit(1); - } - query.close(); - - await Promise.all([ - fs.mkdir(flags.output, { recursive: true }), - fs.mkdir(path.join(flags.output, "graphs"), { recursive: true }), - ]); - - console.log("✨ Bundling..."); - const bundle = await build({ - build: { - lib: { - entry: { - index: path.join(bundleDir, "index.html"), - worker: path.join(bundleDir, "worker.ts"), - }, - name: "Breaboard", - formats: ["es"], - }, - target: "esnext", - write: false, - }, - root: bundleDir, - publicDir: breadboardWebPublic, - logLevel: "silent", - }); - - console.log("🔨 Writing files..."); - if (Array.isArray(bundle)) { - const [{ output }] = bundle; - await Promise.all([ - // Bundler outputs. - ...output.map(async (file) => { - const filePath = path.join(flags.output, file.fileName); - const dir = path.dirname(filePath); - await fs.mkdir(dir, { recursive: true }); - - switch (file.type) { - case "asset": - if (typeof file.source === "string") { - return fs.writeFile(filePath, file.source, { encoding: "utf-8" }); - } else { - return fs.writeFile(filePath, file.source); - } - - case "chunk": - return fs.writeFile(filePath, file.code, { encoding: "utf-8" }); - } - }), - - // The board. - fs.copyFile( - board, - path.join(flags.output, "graphs", "bundled-board.json") - ), - - // Styles. - fs.cp( - path.join(breadboardWebPublic, "styles"), - path.join(flags.output, "styles"), - { recursive: true } - ), - - // Third Party. - fs.cp( - path.join(breadboardWebPublic, "third_party"), - path.join(flags.output, "third_party"), - { recursive: true } - ), - - // Images. - fs.cp( - path.join(breadboardWebPublic, "images"), - path.join(flags.output, "images"), - { recursive: true } - ), - - // Boards. - fs.cp( - path.join(breadboardWebPublic, "graphs"), - path.join(flags.output, "graphs"), - { recursive: true } - ), - ]); - } else { - console.error("Unable to generate bundle - unexpected bundler output"); - process.exit(1); - } - - console.log(`🥳 Written to ${flags.output}`); -} diff --git a/packages/breadboard-cli/src/commands/commandTypes.ts b/packages/breadboard-cli/src/commands/commandTypes.ts deleted file mode 100644 index 2811826570d..00000000000 --- a/packages/breadboard-cli/src/commands/commandTypes.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Options } from "./lib/loader.js"; - -export type RunOptions = Options & { - kit?: string[]; - proxy?: string[]; - proxyNode: string[]; - input?: string; - inputFile?: string; - verbose?: boolean; -}; - -export type DebugOptions = Options & { - kit?: string[]; -}; -export type ImportOptions = Options & { - api?: string; // API URL for import -}; -export type MakeOptions = Options & { - format?: boolean; -}; -export type MermaidOptions = Options; -export type ProxyOptions = Options & { - config?: string; - kit?: string[]; - dist?: string; - port: string; - proxyNode: string[]; -}; diff --git a/packages/breadboard-cli/src/commands/debug.ts b/packages/breadboard-cli/src/commands/debug.ts deleted file mode 100644 index abd8ef49d53..00000000000 --- a/packages/breadboard-cli/src/commands/debug.ts +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import path, { dirname } from "path"; -import { fileURLToPath } from "url"; -import { watch } from "./lib/utils.js"; -import { stat } from "fs/promises"; -import { DebugOptions } from "./commandTypes.js"; -import { startServer } from "./lib/debug-server.js"; - -export const __dirname = dirname(fileURLToPath(import.meta.url)); - -type RenameCallback = (previous: string | null, filename: string) => void; - -/** - * A helper class that collates the rename event from the - * file watcher from two to one event. - * The basic idea is that it waits for the second event - * and if it never comes, it will just emit event. - */ -class RenameCollator { - #timeout: NodeJS.Timeout | null = null; - #callback: RenameCallback; - #counter = 0; - #previousFilename: string | null = null; - - constructor(callback: RenameCallback) { - this.#callback = callback; - } - - onChange(filename: string) { - if (this.#counter === 0) { - this.#previousFilename = filename; - this.#counter++; - this.#timeout = setTimeout(() => { - this.#callback(this.#previousFilename, filename); - }, 300); - } else { - this.#counter = 0; - this.#callback(this.#previousFilename, filename); - this.#previousFilename = null; - if (this.#timeout) { - clearTimeout(this.#timeout); - } - } - } -} - -export const debug = async (file: string, options: DebugOptions) => { - if (file == undefined) { - // If the user doesn't provide a file, we should use the current working directory (which will load all files) - file = process.cwd(); - } - - const outputDirectoryStat = - "output" in options ? await stat(options.output) : undefined; - - options.root = path.parse(path.resolve(file)).dir; - - if (options.save && outputDirectoryStat?.isDirectory() == false) { - console.error( - `The defined output directory ${options.output} is not a directory.` - ); - return process.exit(1); - } - - if (options.save == false && outputDirectoryStat?.isDirectory()) { - console.warn( - `Files will not be output to defined output directory ${options.output} because the -n (no-save) flag was used.` - ); - } - - if ("watch" in options) { - const relative = path.relative(file, options.output); - const isOutputDirectoryContainedWithin = - relative === "" || - (relative && !relative.startsWith("..") && !path.isAbsolute(relative)); - if (options.save && isOutputDirectoryContainedWithin) { - console.error( - `The output directory ${options.output} must be outside of the file or directory being watched. Specify a different output directory with the -o flag.` - ); - return process.exit(1); - } - - const collator = new RenameCollator((previous, filename) => { - notifyClients("rename", previous, filename); - }); - - watch(file, { - onChange: async (filename: string) => { - // Signal that the browser should reload - and it will refresh the - // boards. - console.log(`${filename} changed. Refreshing boards...`); - - notifyClients("change", null, filename); - }, - onRename: async (filename) => { - // Refresh the list of boards that are passed in at the start of the - // server. - console.log(`Refreshing boards...`); - - collator.onChange(filename); - }, - }); - } - - const { notifyClients } = await startServer(file, options); -}; diff --git a/packages/breadboard-cli/src/commands/import.ts b/packages/breadboard-cli/src/commands/import.ts deleted file mode 100644 index e1efa9faf49..00000000000 --- a/packages/breadboard-cli/src/commands/import.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { stat, writeFile } from "fs/promises"; -import path from "path"; -import { pathToFileURL } from "url"; -import { ImportOptions } from "./commandTypes.js"; -import { OpenAPIBoardBuilder } from "@breadboard-ai/import"; - -export const importGraph = async (url: string, options: ImportOptions) => { - if (URL.canParse(url) == false) { - const fileStat = await stat(path.resolve(process.cwd(), url)); - if (fileStat != undefined && fileStat.isFile()) { - // We think it's a file. - url = pathToFileURL(url).toString(); - } else { - throw new Error("Invalid URL"); - } - } - - const apiPathFilter = options.api; - const outputPath = options.output; - - if (apiPathFilter == undefined && outputPath == undefined) { - console.error( - "You must specify either -a (an API) or a directory to output all of the APIs to." - ); - return; - } - - const builder = new OpenAPIBoardBuilder(url); - - for await (const { board, apiSpec } of builder.build()) { - console.log(board); - if (apiSpec.operationId != undefined && outputPath != undefined) { - await outputBoard(board, apiSpec.operationId, outputPath); - } - } -}; - -const outputBoard = async ( - board: unknown, - apiPath: string, - outputPath: string -) => { - const boardJSON = JSON.stringify(board); - const boardName = apiPath; - const boardPath = path.join( - path.resolve(process.cwd(), outputPath), - `${boardName}.json` - ); - writeFile(boardPath, boardJSON, { encoding: "utf-8" }); -}; diff --git a/packages/breadboard-cli/src/commands/lib/debug-routes/board.ts b/packages/breadboard-cli/src/commands/lib/debug-routes/board.ts deleted file mode 100644 index 20ffcd8884b..00000000000 --- a/packages/breadboard-cli/src/commands/lib/debug-routes/board.ts +++ /dev/null @@ -1,42 +0,0 @@ -import http from "http"; -import { ServerGlobals } from "../debug-server.js"; -import { extname, join } from "path"; -import { loadBoards } from "../utils.js"; - -export async function board( - request: http.IncomingMessage, - response: http.ServerResponse, - match: URLPatternResult, - globals: ServerGlobals -) { - const { boards, options, base } = globals; - const requestURL = new URL(request.url ?? "", base); - let board = boards.find((board) => board.url == requestURL.pathname); - if (!board) { - const isKitManifest = requestURL.pathname.endsWith(".kit.json"); - const isJSON = extname(requestURL.pathname) === ".json"; - const isTypeScript = extname(requestURL.pathname) === ".ts"; - if (isTypeScript || (isJSON && !isKitManifest)) { - // Attempt to load the board and append it to the list of boards. - const possibleBoardPath = join(globals.file, requestURL.pathname); - try { - const newBoards = await loadBoards(possibleBoardPath, options); - const [newBoard] = newBoards; - boards.push(newBoard); - board = newBoard; - } catch (err) { - console.error("Unable to find board at", possibleBoardPath); - } - } - } - - // We only want to serve the file that is being debugged... nothing else. - if (board) { - const boardData = JSON.stringify(board); - response.writeHead(200, { - "Content-Type": "application/json", - }); - - return response.end(boardData); - } -} diff --git a/packages/breadboard-cli/src/commands/lib/debug-routes/boards.ts b/packages/breadboard-cli/src/commands/lib/debug-routes/boards.ts deleted file mode 100644 index 692b2bc95d7..00000000000 --- a/packages/breadboard-cli/src/commands/lib/debug-routes/boards.ts +++ /dev/null @@ -1,31 +0,0 @@ -import http from "http"; -import { loadBoards } from "../utils.js"; -import { ServerGlobals } from "../debug-server.js"; - -export async function boardList( - _request: http.IncomingMessage, - response: http.ServerResponse, - _match: URLPatternResult, - globals: ServerGlobals -) { - const { file, options } = globals; - const boards = await loadBoards(file, options); - globals.boards = boards; - - const boardsData = JSON.stringify( - boards - .map((board) => ({ - url: board.url, - version: board.version, - title: board.title, - })) - .sort((a, b) => a.title.localeCompare(b.title)) - ); - - response.writeHead(200, { - "Content-Type": "application/json", - "Content-Length": boardsData.length, - }); - - return response.end(boardsData); -} diff --git a/packages/breadboard-cli/src/commands/lib/debug-routes/debug.ts b/packages/breadboard-cli/src/commands/lib/debug-routes/debug.ts deleted file mode 100644 index f93afa052ee..00000000000 --- a/packages/breadboard-cli/src/commands/lib/debug-routes/debug.ts +++ /dev/null @@ -1,25 +0,0 @@ -import http from "http"; -import { ServerGlobals } from "../debug-server.js"; - -export async function debug( - request: http.IncomingMessage, - response: http.ServerResponse, - match: URLPatternResult, - globals: ServerGlobals -) { - const { clients } = globals; - - response.writeHead(200, { - "Content-Type": "text/event-stream", - "Cache-Control": "no-cache", - Connection: "keep-alive", - }); - const clientId = - Date.now() + - Buffer.from(crypto.getRandomValues(new Uint32Array(10))).toString("hex"); - response.on("close", () => { - delete clients[clientId]; - }); - clients[clientId] = response; - return response; -} diff --git a/packages/breadboard-cli/src/commands/lib/debug-routes/kit.ts b/packages/breadboard-cli/src/commands/lib/debug-routes/kit.ts deleted file mode 100644 index f8bf9f15403..00000000000 --- a/packages/breadboard-cli/src/commands/lib/debug-routes/kit.ts +++ /dev/null @@ -1,28 +0,0 @@ -import http from "http"; -import { ServerGlobals } from "../debug-server.js"; - -export async function kit( - request: http.IncomingMessage, - response: http.ServerResponse, - match: URLPatternResult, - globals: ServerGlobals -) { - const { kits } = globals; - const { kitName } = match.pathname.groups; - const kit = kits.find((kit) => kit.file === kitName); - if (kit) { - if ("data" in kit) { - response.writeHead(200, { - "Content-Type": "application/javascript", - }); - - return response.end(kit.data); - } else { - response.writeHead(302, { - Location: kit.url, - }); - return response.end(); - } - } - return response.end(); -} diff --git a/packages/breadboard-cli/src/commands/lib/debug-routes/kits.ts b/packages/breadboard-cli/src/commands/lib/debug-routes/kits.ts deleted file mode 100644 index d0669f6a342..00000000000 --- a/packages/breadboard-cli/src/commands/lib/debug-routes/kits.ts +++ /dev/null @@ -1,21 +0,0 @@ -import http from "http"; -import { ServerGlobals } from "../debug-server.js"; - -export async function kits( - request: http.IncomingMessage, - response: http.ServerResponse, - match: URLPatternResult, - globals: ServerGlobals -) { - const { kits } = globals; - const responseText = JSON.stringify( - kits.map((kit) => `/kits/${kit.file}`) || [] - ); - - response.writeHead(200, { - "Content-Type": "application/javascript", - "Content-Length": responseText.length, - }); - - return response.end(responseText); -} diff --git a/packages/breadboard-cli/src/commands/lib/debug-server.ts b/packages/breadboard-cli/src/commands/lib/debug-server.ts deleted file mode 100644 index 41b9b05e4db..00000000000 --- a/packages/breadboard-cli/src/commands/lib/debug-server.ts +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import http, { IncomingMessage, ServerResponse } from "http"; -import { join, relative } from "path"; -import handler from "serve-handler"; -import { pathToFileURL, URL } from "url"; -import { BoardMetaData, SERVER_PORT, SERVER_URL, defaultKits } from "./utils.js"; -import { stat } from "fs/promises"; -import { URLPattern } from "urlpattern-polyfill"; - -import { DebugOptions } from "../commandTypes.js"; -import { __dirname } from "../debug.js"; -import { KitData, getKits } from "./kits.js"; - -import { boardList } from "./debug-routes/boards.js"; -import { kits } from "./debug-routes/kits.js"; -import { kit } from "./debug-routes/kit.js"; -import { debug } from "./debug-routes/debug.js"; -import { board } from "./debug-routes/board.js"; - -export type Routes = Record< - string, - ( - request: http.IncomingMessage, - response: http.ServerResponse, - match: URLPatternResult, - globals: ServerGlobals - ) => Promise | void> ->; - -export type ServerGlobals = { - distDir: string; - fileUrl: URL; - isDirectory: boolean; - boards: Array; - file: string; - options: DebugOptions; - kits: Array; - base: URL; - clients: Record; -}; - -// This is the main routing table for the debug server. -const routes: Routes = { - "/api/board/list": boardList, - "/kits.json": kits, - "/kits/:kitName(.*)": kit, - "/~~debug": debug, - "/*.(json|ts)": board, // after kits.json -}; - -const removeBoardFromCache = ( - boards: BoardMetaData[], - filename: string | null -) => { - if (!filename) return; - const toRemove = boards - .filter(Boolean) - .findIndex((board) => board.url?.endsWith(filename)); - boards.splice(toRemove, 1); -}; - -export const startServer = async (file: string, options: DebugOptions) => { - const distDir = join(__dirname, "..", "..", "debugger"); - const fileStat = await stat(file); - const fileUrl = pathToFileURL(file); - const isDirectory = fileStat.isDirectory(); - const boards: Array = []; // Boards are dynamically loaded based on the "/boards.js" request. - const kits = await getKits(defaultKits, options.kit); - const clients: Record = {}; - const base = new URL(SERVER_URL); - - const globals: ServerGlobals = { - distDir, - fileUrl, - isDirectory, - boards, - file, - options, - kits, - clients, - base, - }; - - const notifyClients = ( - type: "change" | "rename", - previous: string | null, - filename: string - ) => { - removeBoardFromCache(globals.boards, previous); - removeBoardFromCache(globals.boards, filename); - Object.values(clients).forEach((clientResponse) => { - clientResponse.write( - `event: update\ndata:${JSON.stringify({ type, previous, filename })}\nid:${Date.now()}\n\n` - ); - }); - }; - - const server = http.createServer(async (request, response) => { - const requestURL = new URL(request.url ?? "", base.origin); - - for (const route in routes) { - const routePattern = new URLPattern(route, base.origin); - const match = routePattern.exec(requestURL); - if (match) { - const routeResponse = await routes[route]( - request, - response, - match, - globals - ); - if (routeResponse == undefined) { - continue; - } else { - return routeResponse; - } - } - } - - return handler(request, response, { - public: distDir, - cleanUrls: ["/"], - }); - }); - - server.listen(SERVER_PORT, () => { - const urlPath = isDirectory - ? "" - : `?board=/${relative(process.cwd(), fileUrl.pathname)}`; - console.log(`Running at ${SERVER_URL}/${urlPath}`); - }); - - return { notifyClients }; -}; diff --git a/packages/breadboard-cli/src/commands/lib/kits.ts b/packages/breadboard-cli/src/commands/lib/kits.ts deleted file mode 100644 index cb1f23d0eaa..00000000000 --- a/packages/breadboard-cli/src/commands/lib/kits.ts +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { rollup } from "rollup"; -import virtualDefault from "@rollup/plugin-virtual"; -import nodeResolveDefault from "@rollup/plugin-node-resolve"; -import commonjsDefault from "@rollup/plugin-commonjs"; - -import jsonDefault from "@rollup/plugin-json"; - -export type KitData = - | { - file: string; - data: string; - } - | { - file: string; - url: string; - }; - -const virtual = virtualDefault as unknown as typeof virtualDefault.default; -const nodeResolve = - nodeResolveDefault as unknown as typeof nodeResolveDefault.default; -const json = jsonDefault as unknown as typeof jsonDefault.default; -const commonjs = commonjsDefault as unknown as typeof commonjsDefault.default; - -const createUniqueName = async (url: string) => { - const a = await crypto.subtle.digest("SHA-1", new TextEncoder().encode(url)); - const uniqueName = Array.from(new Uint8Array(a)) - .map((b) => b.toString(16).padStart(2, "0")) - .join(""); - return url.endsWith(".kit.json") ? `${uniqueName}.kit.json` : uniqueName; -}; - -/* - This function compiles and bundles known 'node_module' into a single string. - - If the compilation fails, it will throw an error and halt the entire application. -*/ -export const compile = async (file: string) => { - console.log(`Compiling ${file}`); - const bundle = await rollup({ - input: "entry", - // Hide our sins like circular dependencies. - logLevel: "silent", - plugins: [ - virtual({ - entry: `import * as kit from "${file}"; export default kit.default;`, - }), - json(), - commonjs(), - nodeResolve(), - ], - }); - - const { output } = await bundle.generate({ format: "es" }); - - return output[0].code; -}; - -const isURLish = (s: string) => { - return URL.canParse(s) || s.startsWith("/"); -}; - -export const getKits = async ( - defaultKits: string[], - specifiedKits: string[] = [] -): Promise => { - const kitNames = [...new Set([...specifiedKits, ...defaultKits])]; - const kits = []; - - for (const kit of kitNames) { - if (isURLish(kit)) { - kits.push({ - file: await createUniqueName(kit), - url: kit, - }); - } else { - kits.push({ - file: kit, - data: await compile(kit), - }); - } - } - - return kits; -}; diff --git a/packages/breadboard-cli/src/commands/lib/loader.ts b/packages/breadboard-cli/src/commands/lib/loader.ts deleted file mode 100644 index ed51abeb52f..00000000000 --- a/packages/breadboard-cli/src/commands/lib/loader.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { SerializableBoard, serialize } from "@breadboard-ai/build"; -import { GraphDescriptor } from "@google-labs/breadboard"; -import { pathToFileURL } from "url"; - -export type Options = { - output: string; - root?: string; - watch?: boolean; - save?: boolean; -}; - -const boardLike = ( - board: Record -): board is GraphDescriptor => { - return board && "edges" in board && "nodes" in board; -}; - -export abstract class Loader { - async loadBoardFromModule(file: string) { - // This will leak. Look for other hot reloading solutions. - let board = (await import(`${file}?${Date.now()}`)).default; - - if (board == undefined) - throw new Error(`Board ${file} does not have a default export`); - - if ("inputs" in board && "outputs" in board) { - // TODO(aomarks) Not a great way to detect build boards. - board = serialize(board as SerializableBoard); - } - - if (boardLike(board)) { - // A graph descriptor has been exported.. Possibly a lambda. - board.url = pathToFileURL(file).href; // So that the base url is correct for subsequent invokes - } - return board; - } - - abstract load( - filePath: string, - options: Options - ): Promise; -} diff --git a/packages/breadboard-cli/src/commands/lib/loaders/index.ts b/packages/breadboard-cli/src/commands/lib/loaders/index.ts deleted file mode 100644 index 0c7c8a90116..00000000000 --- a/packages/breadboard-cli/src/commands/lib/loaders/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { GraphDescriptor } from "@google-labs/breadboard"; -import { JSLoader } from "./javascript.js"; -import { Loader, Options } from "../loader.js"; -import { TypeScriptLoader } from "./typescript.js"; -import { JSONLoader } from "./json.js"; - -const supportedFileTypes = ["js", "ts", "json"] as const; -type LoaderTuple = typeof supportedFileTypes; -type LoaderType = LoaderTuple[number]; - -export class Loaders { - #loaderInstance: { load: Loader["load"] }; - - static get supportedFileTypes(): LoaderTuple { - return supportedFileTypes; - } - - constructor(loader: LoaderType) { - if (loader === "js") { - this.#loaderInstance = new JSLoader(); - } else if (loader === "ts") { - this.#loaderInstance = new TypeScriptLoader(); - } else if (loader === "json") { - this.#loaderInstance = new JSONLoader(); - } else { - throw new Error(`Unsupported file type ${loader}`); - } - } - - async load( - filePath: string, - options: Options - ): Promise { - return this.#loaderInstance.load(filePath, options); - } -} - -export { Loader }; diff --git a/packages/breadboard-cli/src/commands/lib/loaders/javascript.ts b/packages/breadboard-cli/src/commands/lib/loaders/javascript.ts deleted file mode 100644 index ed39a419910..00000000000 --- a/packages/breadboard-cli/src/commands/lib/loaders/javascript.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { GraphDescriptor } from "@google-labs/breadboard"; -import { Loader } from "../loader.js"; -import { resolve } from "path"; - -export class JSLoader extends Loader { - async load(filePath: string): Promise { - const board = await this.loadBoardFromModule( - resolve(process.cwd(), filePath) - ); - return board; - } -} diff --git a/packages/breadboard-cli/src/commands/lib/loaders/json.ts b/packages/breadboard-cli/src/commands/lib/loaders/json.ts deleted file mode 100644 index 36294bb9bd3..00000000000 --- a/packages/breadboard-cli/src/commands/lib/loaders/json.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createLoader, GraphDescriptor } from "@google-labs/breadboard"; -import { Loader } from "../loader.js"; -import { pathToFileURL } from "url"; - -export class JSONLoader extends Loader { - async load(filePath: string): Promise { - const graph = await createLoader().load(filePath, { - base: new URL(pathToFileURL(process.cwd()).toString()), - }); - return graph; - } -} diff --git a/packages/breadboard-cli/src/commands/lib/loaders/typescript.ts b/packages/breadboard-cli/src/commands/lib/loaders/typescript.ts deleted file mode 100644 index d4649fa35b8..00000000000 --- a/packages/breadboard-cli/src/commands/lib/loaders/typescript.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { GraphDescriptor } from "@google-labs/breadboard"; -import esbuild from "esbuild"; -import { readFile, stat, unlink, writeFile } from "fs/promises"; -import { basename, join, resolve, dirname } from "path"; -import { Loader, Options } from "../loader.js"; - -export class TypeScriptLoader extends Loader { - /* - If we are loading from Source (TS) then we need to compile it and output it to a place where there are unlikely to be any collisions. -*/ - async #loadBoardFromSource( - filename: string, - source: string, - options?: Options - ): Promise { - const tmpDir = options?.output ?? process.cwd(); - const randomName = Buffer.from( - crypto.getRandomValues(new Uint32Array(16)) - ).toString("hex"); - const tmpFilePath = join( - tmpDir, - `~${basename(filename, "ts")}${randomName}tmp.mjs` - ); - - let tmpFileStat; - try { - tmpFileStat = await stat(tmpFilePath); - } catch (e) { - // Don't care if the file doesn't exist. It's fine. It's what we want. - ("Nothing to see here. Just don't want to have to re-throw."); - } - - if (tmpFileStat && tmpFileStat.isFile()) { - // Don't write to a file. - throw new Error( - `The temporary file ${tmpFilePath} already exists. We can't write to it.` - ); - } - - if (tmpFileStat && tmpFileStat.isSymbolicLink()) { - // Don't write to a symbolic link. - throw new Error( - `The file ${tmpFilePath} is a symbolic link. We can't write to it.` - ); - } - - if (tmpFileStat && tmpFileStat.isDirectory() == false) { - // Don't write to a directory. - throw new Error( - `The file ${tmpFilePath} is a directory. We can't write to it.` - ); - } - - try { - // I heard it might be possible to do a symlink hijack. double check. - await writeFile(tmpFilePath, source); - - // For the import to work it has to be relative to the current working directory. - const board = await this.loadBoardFromModule( - resolve(process.cwd(), tmpFilePath) - ); - - return board; - } catch (e) { - console.error(e); - return null; - } finally { - tmpFileStat = await stat(tmpFilePath); - // remove the file - if (tmpFileStat && tmpFileStat.isFile()) { - await unlink(tmpFilePath); - } - } - } - - async #makeFromSource( - filename: string, - source: string, - options?: Options - ): Promise<{ boardJson: string; board: GraphDescriptor }> { - const board = await this.#loadBoardFromSource(filename, source, options); - if (board == undefined) { - throw new Error("Failed to load board from source"); - } - const boardJson = JSON.stringify(board, null, 2); - return { boardJson, board }; - } - - async load( - filePath: string, - options: Options - ): Promise { - const fileContents = await readFile(filePath, "utf-8"); - - const result = await esbuild.build({ - stdin: { - contents: fileContents, - resolveDir: dirname(filePath), - loader: "ts", - }, - format: "esm", - platform: "browser", - external: ["node:fs/promises", "node:vm"], - bundle: true, - minify: false, - write: false, - }); - - const source = new TextDecoder().decode(result.outputFiles[0].contents); - - const { board } = await this.#makeFromSource(filePath, source, options); - - return board; - } -} diff --git a/packages/breadboard-cli/src/commands/lib/proxy-server.ts b/packages/breadboard-cli/src/commands/lib/proxy-server.ts deleted file mode 100644 index bd950777469..00000000000 --- a/packages/breadboard-cli/src/commands/lib/proxy-server.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { - AnyProxyRequestMessage, - HTTPServerTransport, - ProxyServer, - ProxyServerConfig, - ServerResponse, -} from "@google-labs/breadboard/remote"; -import http from "http"; -import handler from "serve-handler"; - -const extractRequestBody = async (request: http.IncomingMessage) => { - return new Promise((resolve, reject) => { - let body = ""; - request.on("data", (chunk) => { - body += chunk.toString(); - }); - request.on("end", () => { - resolve(JSON.parse(body) as AnyProxyRequestMessage); - }); - request.on("error", reject); - }); -}; - -/* - This is a simple implementation of a ResponseHandler for the HTTPServerProxyTransport. It maps http.ServerResponse on to an express-lie response object. -*/ -class ResponseHandler implements ServerResponse { - #response: http.ServerResponse; - constructor(private response: http.ServerResponse) { - this.#response = response; - } - - header(field: string, value: string) { - this.#response.setHeader(field, value); - return; - } - write(chunk: unknown) { - return this.#response.write(chunk); - } - end() { - this.#response.end(); - } -} - -export const startServer = async ( - dist: string, - port: string, - config: ProxyServerConfig -) => { - const server = http.createServer(async (request, response) => { - if (request.method === "POST") { - const body = await extractRequestBody(request); - const responseHandler = new ResponseHandler(response); - - const server = new ProxyServer( - new HTTPServerTransport({ body }, responseHandler) - ); - try { - await server.serve(config); - } catch (e) { - response.statusCode = 500; - response.write(`500 Server Error: ${(e as Error).message}`); - } - return; - } - - return handler(request, response, { - public: dist, - cleanUrls: ["/"], - }); - }); - - server.listen(port, () => { - console.log(`Running at http://localhost:${port}/`); - }); -}; diff --git a/packages/breadboard-cli/src/commands/lib/utils.ts b/packages/breadboard-cli/src/commands/lib/utils.ts deleted file mode 100644 index b26766833f6..00000000000 --- a/packages/breadboard-cli/src/commands/lib/utils.ts +++ /dev/null @@ -1,243 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "@google-labs/breadboard"; -import { Dirent, watch as fsWatch } from "fs"; -import { opendir, readFile, stat, writeFile, mkdir } from "fs/promises"; -import { join } from "node:path"; -import { stdin as input } from "node:process"; -import * as readline from "node:readline/promises"; -import path, { extname } from "path"; -import { relative } from "path/posix"; -import { URL, pathToFileURL } from "url"; -import { Options } from "./loader.js"; -import { Loaders } from "./loaders/index.js"; -import { MakeOptions } from "../commandTypes.js"; -import { formatGraphDescriptor } from "@google-labs/breadboard"; - -export const SERVER_PORT = parseInt(process.env.PORT || "") || 3000; -export const SERVER_URL = `http://localhost:${SERVER_PORT}`; - -export const defaultKits = [ - "@google-labs/palm-kit", - "@google-labs/core-kit", - "@google-labs/json-kit", - "@google-labs/template-kit", - "@google-labs/node-nursery-web", - `/agent.kit.json`, -]; - -export type BoardMetaData = { - title: string; - url?: string; - version: string; - edges: Array; - nodes: Array; - kits: Array; -}; - -export type WatchOptions = { - onChange: (filename: string) => void; - onRename?: (filename: string) => void; - controller?: AbortController; -}; - -export const watch = (file: string, options: WatchOptions) => { - let { controller, onChange, onRename } = options; - - onChange = onChange ?? (() => ""); - onRename = - onRename ?? - ((filename) => - console.error( - `File ${filename} has been renamed. We can't manage this yet. Sorry!` - )); - - controller = controller ?? new AbortController(); - - fsWatch( - file, - { signal: controller.signal, recursive: true }, - async (eventType: string, filename: string | Buffer | null) => { - if (typeof filename != "string") return; - - if (eventType === "change") { - onChange(filename); - } else if (eventType === "rename") { - if (onRename != undefined) { - onRename(filename); - } - } - } - ); -}; - -export const resolveFilePath = (file: string) => { - return path.resolve( - process.cwd(), - path.join(path.dirname(file), path.basename(file)) - ); -}; - -export const loadBoard = async ( - file: string, - options: MakeOptions -): Promise => { - const loaderType = extname(file).slice(1) as "js" | "ts" | "json"; - const save = "save" in options ? options["save"] : true; - - const loader = new Loaders(loaderType); - const board = await loader.load(file, options); - if (save) { - let boardClone = JSON.parse(JSON.stringify(board)); - delete boardClone.url; // Boards shouldn't have URLs serialized. - if (options.format) { - boardClone = formatGraphDescriptor(boardClone); - } - const boardJson = JSON.stringify(boardClone, null, 2); - - // Most commands will pass in the output directory, but if they don't, we'll use the directory of the file being loaded. - const outputFilePath = await resolveAndCreateOutputDirectory(options, file); - await writeFile(outputFilePath, boardJson); - } - return board; -}; - -export const parseStdin = async (): Promise => { - let lines = ""; - const rl = readline.createInterface({ input }); - for await (const line of rl) { - lines += line; - } - rl.close(); - return lines; -}; - -const showError = (e: unknown, path?: string) => { - const error = e as Error; - console.error(`Failed to load board at "${path}": ${error.message}`); -}; - -export const loadBoards = async ( - path: string, - options: Options -): Promise> => { - const fileStat = await stat(path); - const fileUrl = pathToFileURL(path); - - if (fileStat && fileStat.isFile() && path.endsWith(".json")) { - try { - const data = await readFile(path, { encoding: "utf-8" }); - const board = JSON.parse(data) as GraphDescriptor; // assume conversion would fail if it wasn't a graph descriptor. - - return [ - { - edges: board.edges ?? [], - nodes: board.nodes ?? [], - kits: board.kits ?? [], - title: board.title ?? path, - url: join("/", relative(process.cwd(), path)), - version: board.version ?? "0.0.1", - }, - ]; - } catch (e) { - showError(e, path); - } - } - - if ( - fileStat && - fileStat.isFile() && - (path.endsWith(".js") || path.endsWith(".ts") || path.endsWith(".json")) - ) { - try { - // Compile the JS or TS. - const board = await loadBoard(path, options); - - return [ - { - ...(board || {}), - title: board?.title ?? path, - url: join("/", relative(process.cwd(), path)), - version: board?.version ?? "0.0.1", - } as BoardMetaData, - ]; - } catch (e) { - showError(e, path); - } - } - - if (fileStat && fileStat.isDirectory()) { - return await loadBoardsFromDirectory(fileUrl, path, options); - } - - return []; -}; - -const getFilename = (dirent: Dirent) => { - const { path: maybePath, name } = dirent; - // In Node v20.5.0 and earlier, the name is included in path - // In Node v20.6.0 and later, the name is not included in path - return maybePath.endsWith(name) ? maybePath : join(maybePath, name); -}; - -async function resolveAndCreateOutputDirectory(options: Options, file: string) { - const outputRoot = - "output" in options ? options["output"] : path.dirname(file); - const inputBaseDirectory = options.root - ? path.resolve(options.root) - : path.dirname(file); - - const pathInfo = path.parse(file); - const fullOutputRootPath = path.resolve(outputRoot); - const inputRoot = path.relative(inputBaseDirectory, pathInfo.dir); - const base = path.join(fullOutputRootPath, inputRoot); - const outputFilePath = path.join(base, `${pathInfo.name}.json`); - await mkdir(base, { recursive: true }); - return outputFilePath; -} - -async function loadBoardsFromDirectory( - fileUrl: URL, - path: string, - options: Options -) { - const dir = await opendir(fileUrl); - const boards: Array = []; - for await (const dirent of dir) { - const name = dirent.name; - if ( - dirent.isFile() && - (name.endsWith(".js") || name.endsWith(".ts") || name.endsWith(".json")) - ) { - const filename = getFilename(dirent); - try { - const board = await loadBoard(filename, options); - boards.push({ - ...board, - title: board?.title ?? name, - url: `/${name}`, - version: board?.version ?? "0.0.1", - } as BoardMetaData); - } catch (e) { - showError(e, filename); - } - } - - if (dirent.isDirectory()) { - const baseFolder = fileUrl.pathname.endsWith("/") - ? fileUrl.pathname - : `${fileUrl.pathname}/`; - const boardsInDir = await loadBoardsFromDirectory( - new URL(dirent.name, pathToFileURL(baseFolder)), - join(path, dirent.name), - options - ); - boards.push(...boardsInDir); - } - } - return boards; -} diff --git a/packages/breadboard-cli/src/commands/lib/verbose-logging-probe.ts b/packages/breadboard-cli/src/commands/lib/verbose-logging-probe.ts deleted file mode 100644 index 2e2beb5dbfc..00000000000 --- a/packages/breadboard-cli/src/commands/lib/verbose-logging-probe.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Probe, ProbeMessage } from "@google-labs/breadboard"; - -export type VerboseLoggingCallback = (message: ProbeMessage) => Promise; - -export class VerboseLoggingProbe extends EventTarget implements Probe { - #callback: VerboseLoggingCallback; - - constructor(callback: VerboseLoggingCallback) { - super(); - this.#callback = callback; - } - - async report(message: ProbeMessage): Promise { - return this.#callback(message); - } -} diff --git a/packages/breadboard-cli/src/commands/make-graph.ts b/packages/breadboard-cli/src/commands/make-graph.ts deleted file mode 100644 index 29d4ebf5762..00000000000 --- a/packages/breadboard-cli/src/commands/make-graph.ts +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import path from "path"; -import { stat } from "fs/promises"; -import { loadBoards, loadBoard, resolveFilePath, watch } from "./lib/utils.js"; -import { MakeOptions } from "./commandTypes.js"; - -export const makeGraph = async (file: string, options: MakeOptions) => { - if (file == undefined) { - // If the user doesn't provide a file, we should use the current working directory (which will load all files) - file = process.cwd(); - } - - const inputFileStat = await stat(file); - - const outputDirectoryStat = - "output" in options ? await stat(options.output) : undefined; - - options.root = path.parse(path.resolve(file)).dir; - - if (outputDirectoryStat?.isDirectory() == false) { - console.error( - `The defined output directory ${options.output} is not a directory.` - ); - return process.exit(1); - } - - if (file != undefined) { - const filePath = resolveFilePath(file); - - if (inputFileStat.isDirectory()) { - // If the input is a directory, we should load all the boards in the directory and save them. - options.save = true; - const relative = path.relative(file, options.output); - const isOutputDirectoryContainedWithin = - relative === "" || - (relative && !relative.startsWith("..") && !path.isAbsolute(relative)); - if (options.save && isOutputDirectoryContainedWithin) { - console.error( - `The output directory ${options.output} must be outside of the file or directory being watched. Specify a different output directory with the -o flag.` - ); - return process.exit(1); - } - - await loadBoards(filePath, options); - } else if (path.extname(file) == ".js" || path.extname(file) == ".ts") { - const board = await loadBoard(filePath, options); - if (options.save == false) { - console.log(JSON.stringify(board, null, 2)); - } - } else { - throw new Error(`File ${file} must be a JavaScript or TypeScript file.`); - } - - if ("watch" in options) { - watch(file, { - onChange: async () => { - if (inputFileStat?.isDirectory()) { - options.save = true; - await loadBoards(filePath, options); - } else { - await loadBoard(filePath, options); - } - }, - }); - } - } -}; diff --git a/packages/breadboard-cli/src/commands/mermaid.ts b/packages/breadboard-cli/src/commands/mermaid.ts deleted file mode 100644 index a1932ad501c..00000000000 --- a/packages/breadboard-cli/src/commands/mermaid.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { toMermaid } from "@google-labs/breadboard"; -import { loadBoard, parseStdin, resolveFilePath, watch } from "./lib/utils.js"; -import { MermaidOptions } from "./commandTypes.js"; - -export const mermaid = async (file: string, options: MermaidOptions) => { - if (file != undefined) { - const filePath = resolveFilePath(file); - let board = await loadBoard(filePath, options); - - if (!board) { - return; - } - - console.log(toMermaid(board)); - - if ("watch" in options) { - watch(file, { - onChange: async () => { - board = await loadBoard(filePath, options); - if (!board) { - return; - } - console.log(toMermaid(board)); - }, - }); - } - } else { - const stdin = await parseStdin(); - - // TODO: What do we do if it's typescript? - // We should validate it looks like a board... - const board = JSON.parse(stdin); - - console.log(toMermaid(board)); - } -}; diff --git a/packages/breadboard-cli/src/commands/proxy.ts b/packages/breadboard-cli/src/commands/proxy.ts deleted file mode 100644 index 8c4f5aa9eaa..00000000000 --- a/packages/breadboard-cli/src/commands/proxy.ts +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { asRuntimeKit } from "@google-labs/breadboard"; -import { ProxyOptions } from "./commandTypes.js"; -import { startServer as startProxyServer } from "./lib/proxy-server.js"; -import { ProxyServerConfig } from "@google-labs/breadboard/remote"; -import { pathToFileURL } from "url"; -import { readFile } from "fs/promises"; - -// The config file format. It's based on ProxyServerConfig, but the kits are strings. -type SimpleProxyServerConfig = Omit & { - kits: string[]; -}; - -export const proxy = async (options: ProxyOptions) => { - const kitDeclarations = options.kit as string[] | undefined; - const proxyNodeDeclarations = options.proxyNode as string[] | undefined; - const port = options.port; - - let config: ProxyServerConfig; - - if (options.config != undefined) { - if (kitDeclarations != undefined || proxyNodeDeclarations != undefined) { - console.warn( - "You are using a config file and specifying kits and proxy nodes. The config file will override the command line options." - ); - } - config = await loadConfig(options); - } else { - config = { kits: [], proxy: [] }; - - if (kitDeclarations != undefined) { - // We should warn if we are importing code and the associated risks - config.kits = await loadKits(kitDeclarations); - } else { - throw new Error("You must specify at least one kit."); - } - - if ( - proxyNodeDeclarations != undefined && - proxyNodeDeclarations.length == 0 - ) { - throw new Error( - "You must specify at least one proxy node if you are using a proxy." - ); - } - - config.proxy = proxyNodeDeclarations || []; - } - - await startProxyServer(options.dist || process.cwd(), port, config); -}; - -async function loadConfig(options: ProxyOptions): Promise { - const config: ProxyServerConfig = { - kits: [], - proxy: [], - }; - - if (options.config == undefined) { - throw new Error("You must specify a config file."); - } - - const fileUrl = pathToFileURL(options.config); - - const importedConfig = JSON.parse( - await readFile(fileUrl.pathname, { encoding: "utf-8" }) - ) as SimpleProxyServerConfig; - - if (importedConfig == undefined) { - throw new Error("The config file must export a default object."); - } - - if (importedConfig.kits == undefined || importedConfig.proxy == undefined) { - throw new Error( - "The config file must have at least one kit and one proxy property." - ); - } - - config.kits = await loadKits(importedConfig.kits); - - if (importedConfig.proxy) { - config.proxy = importedConfig.proxy; - } - return config; -} - -async function loadKits( - kits: SimpleProxyServerConfig["kits"] -): Promise { - const loadedKits: ProxyServerConfig["kits"] = []; - for (const kitDetail of kits) { - const kitImport = await import(kitDetail); - loadedKits.push(asRuntimeKit(kitImport.default)); - } - return loadedKits; -} diff --git a/packages/breadboard-cli/src/commands/run.ts b/packages/breadboard-cli/src/commands/run.ts deleted file mode 100644 index 68752d4abc1..00000000000 --- a/packages/breadboard-cli/src/commands/run.ts +++ /dev/null @@ -1,166 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphDescriptor, - InputValues, - Kit, - Schema, - asRuntimeKit, - runGraph, -} from "@google-labs/breadboard"; -import { loadBoard, parseStdin, resolveFilePath, watch } from "./lib/utils.js"; -import * as readline from "node:readline/promises"; -import { stdin as input, stdout as output } from "node:process"; -import { VerboseLoggingProbe } from "./lib/verbose-logging-probe.js"; -import { RunOptions } from "./commandTypes.js"; -import { readFile } from "node:fs/promises"; -import { pathToFileURL } from "url"; -import { - HTTPClientTransport, - ProxyClient, -} from "@google-labs/breadboard/remote"; - -async function runBoard( - board: GraphDescriptor, - inputs: InputValues, - kits: Kit[], - verbose: boolean, - pipedInput = false -) { - const probe = verbose - ? new VerboseLoggingProbe(async (data) => console.log(data)) - : undefined; - - for await (const stop of runGraph(board, { - kits, - probe, - })) { - if (stop.type === "input") { - const nodeInputs = stop.inputArguments; - // we won't mutate the inputs. - const newInputs = { ...inputs }; - const schema = nodeInputs.schema as Schema; - - /* - We will ask for the data if it's not present on the inputs. - However we can't ask for prompts if the graph has been piped in. - */ - if (pipedInput == false) { - const rl = readline.createInterface({ input, output }); - - if (schema != undefined && schema.properties != undefined) { - const properties = Object.entries(schema.properties); - const required = schema.required || []; - - for (const [name, property] of properties) { - if (name in newInputs == false) { - // There is no input being passed in already. - let answer; - if (required.indexOf(name) >= 0) { - // The argument is *required*, even if there is a default ask for it. - answer = await rl.question( - `(${name}) ${property.description}:` - ); - } else { - answer = property.default; - } - - newInputs[name] = answer; - } - } - stop.inputs = newInputs; - } - - rl.close(); - } - } else if (stop.type === "output") { - console.log(stop.outputs); - } - } -} - -const loadInputFile = async (filePath: string): Promise => { - const fileUrl = pathToFileURL(filePath); - - return JSON.parse( - await readFile(fileUrl.pathname, { encoding: "utf-8" }) - ) as InputValues; -}; - -export const run = async (file: string, options: RunOptions) => { - const proxy = options.proxy as string | undefined; - const kitDeclarations = options.kit as string[] | undefined; - const proxyNodeDeclarations = options.proxyNode as string[] | undefined; - const verbose = "verbose" in options; - const optionsInput = options.input - ? (JSON.parse(options.input) as InputValues) - : {}; - - const input = options.inputFile - ? { ...(await loadInputFile(options.inputFile)), ...optionsInput } // Allow merging of input file and CLI input - : optionsInput; - - const kits: Kit[] = []; - - if (kitDeclarations != undefined) { - // We should warn if we are importing code and the associated risks - for (const kitDetail of kitDeclarations) { - const kitImport = await import(kitDetail); - kits.push(asRuntimeKit(kitImport.default)); - } - } - - if ( - proxy != undefined && - ("proxyNode" in options == false || options.proxyNode.length == 0) - ) { - throw new Error( - "You must specify at least one proxy node if you are using a proxy." - ); - } - - if (proxy != undefined && proxyNodeDeclarations != undefined) { - // We should warn if we are importing code and the associated risks - const client = new ProxyClient(new HTTPClientTransport(proxy)); - kits.unshift(client.createProxyKit(proxyNodeDeclarations)); - } - - if (file != undefined) { - const filePath = resolveFilePath(file); - - let board = await loadBoard(filePath, options); - if (!board) { - return; - } - - // We always have to run the board once. - await runBoard(board, input, kits, verbose); - - // If we are watching, we need to run the board again when the file changes. - if ("watch" in options) { - watch(file, { - onChange: async () => { - // Now the board has changed, we need to reload it and run it again. - board = await loadBoard(filePath, options); - if (!board) { - return; - } - // We might want to clear the console here. - await runBoard(board, input, kits, verbose); - }, - }); - } - } else { - const stdin = await parseStdin(); - - // TODO: What do we do if it's typescript? - // We should validate it looks like a board... - const board = JSON.parse(stdin); - - await runBoard(board, input, kits, verbose, true); - } -}; diff --git a/packages/breadboard-cli/src/debugger/index.html b/packages/breadboard-cli/src/debugger/index.html deleted file mode 100644 index d71821f6988..00000000000 --- a/packages/breadboard-cli/src/debugger/index.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - Debugger - - - - - - diff --git a/packages/breadboard-cli/src/debugger/preview.html b/packages/breadboard-cli/src/debugger/preview.html deleted file mode 100644 index 9f9b707bd83..00000000000 --- a/packages/breadboard-cli/src/debugger/preview.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - Preview - - - - - - - - diff --git a/packages/breadboard-cli/src/debugger/provider.ts b/packages/breadboard-cli/src/debugger/provider.ts deleted file mode 100644 index b933c6543f0..00000000000 --- a/packages/breadboard-cli/src/debugger/provider.ts +++ /dev/null @@ -1,180 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphProviderChange, - ChangeNotificationCallback, - GraphDescriptor, - GraphProvider, - GraphProviderCapabilities, - GraphProviderExtendedCapabilities, - GraphProviderStore, -} from "@google-labs/breadboard"; - -type BoardInfo = { - title: string; - url: string; - version?: string; -}; - -const api = { - loadBoards: async () => { - const data = await fetch("/api/board/list"); - const boards = await data.json(); - return boards; - }, - listenForChanges: (callback: (data: GraphProviderChange) => void) => { - const evtSource = new EventSource("/~~debug"); - evtSource.addEventListener("update", (evt) => { - let data: GraphProviderChange; - try { - data = JSON.parse(evt.data); - } catch (e) { - console.error("Failed to parse update event", evt.data); - return; - } - callback(data); - }); - }, -}; - -export class DebuggerGraphProvider implements GraphProvider { - name = "DebuggerGraphProvider"; - - #blank: URL | null = null; - #items: Map = new Map(); - #ready = Promise.resolve(); - - ready() { - return this.#ready; - } - - items(): Map { - return this.#items; - } - - isSupported(): boolean { - return true; - } - - canProvide(_url: URL): false | GraphProviderCapabilities { - // Never use this provider for loading. - return false; - } - - extendedCapabilities(): GraphProviderExtendedCapabilities { - return { - modify: false, - connect: false, - disconnect: false, - refresh: false, - watch: true, - preview: false, - }; - } - - async load(_url: URL): Promise { - throw new Error( - "The `DebuggerGraphProvider` should not be used to load graphs." - ); - } - - async save( - _url: URL, - _descriptor: GraphDescriptor - ): Promise<{ result: boolean; error?: string }> { - throw new Error( - "The `DebuggerGraphProvider` should not be used to save graphs." - ); - } - - async createBlank( - _url: URL - ): Promise<{ result: boolean; error?: string | undefined }> { - throw new Error( - "The `DebuggerGraphProvider` should not be used to create blank graphs." - ); - } - - async create( - _url: URL, - _descriptor: GraphDescriptor - ): Promise<{ result: boolean; error?: string | undefined }> { - throw new Error( - "The `DebuggerGraphProvider` should not be used to create graphs." - ); - } - - async delete( - _url: URL - ): Promise<{ result: boolean; error?: string | undefined }> { - throw new Error( - "The `DebuggerGraphProvider` should not be used to delete graphs." - ); - } - - async connect(_location?: string | undefined): Promise { - throw new Error( - "The `DebuggerGraphProvider` should not be called to connect." - ); - } - - async disconnect(_location?: string | undefined): Promise { - throw new Error( - "The `DebuggerGraphProvider` should not be called to disconnect." - ); - } - - async refresh(_location: string): Promise { - throw new Error( - "The `DebuggerGraphProvider` should not be called to refresh." - ); - } - - async createURL(_location: string, _fileName: string): Promise { - throw new Error( - "The `DebuggerGraphProvider` should not be called to create URL." - ); - } - - async preview(_url: URL): Promise { - throw new Error( - "The `DebuggerGraphProvider` should not be called to preview" - ); - } - - parseURL(_url: URL): { location: string; fileName: string } { - throw new Error( - "The `DebuggerGraphProvider` should not be called to parse URL." - ); - } - - async restore(): Promise { - const boards = (await api.loadBoards()) as BoardInfo[]; - const boardMap = new Map( - boards.map((board) => { - return [ - board.title, - { url: board.url, mine: true, readonly: false, handle: undefined }, - ]; - }) - ); - this.#blank = new URL(boards[0].url, window.location.href); - this.#items.set("debugger", { - permission: "granted", - title: "Boards to Debug", - items: boardMap, - }); - } - - startingURL(): URL | null { - return this.#blank; - } - - watch(callback: ChangeNotificationCallback): void { - api.listenForChanges(callback); - } -} diff --git a/packages/breadboard-cli/src/debugger/settings.ts b/packages/breadboard-cli/src/debugger/settings.ts deleted file mode 100644 index 2857fa7f0e0..00000000000 --- a/packages/breadboard-cli/src/debugger/settings.ts +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -// This is currently a duplicate of types in "@breadboard-ai/visual-editor" -// and is definitely not the final shape of things. -// TODO: Move all these to "@breadboard-ai/settings" or something like that. - -export type SettingValue = { - id?: string; - name: string; - description?: string; - value: string | number | boolean; -}; - -export type SettingEntry = { - key: string; - value: SettingValue; -}; - -export enum SETTINGS_TYPE { - SECRETS = "Secrets", - GENERAL = "General", -} - -export type SettingsList = { - [SETTINGS_TYPE.GENERAL]: SettingEntry; - [SETTINGS_TYPE.SECRETS]: SettingEntry; -}; - -export type SettingsSection = { - configuration: { - extensible: boolean; - description: string; - nameEditable: boolean; - }; - items: Map; -}; - -export type Settings = { - [K in keyof SettingsList]: SettingsSection; -}; - -export type SettingsProvider = { - values: Settings; - getSection(section: SETTINGS_TYPE): SettingsSection; - getItem(section: SETTINGS_TYPE, name: string): SettingValue | undefined; - save(settings: Settings): Promise; - restore(): Promise; -}; - -const SETTINGS_KEY = "bb-settings-store"; - -const replacer = (key: string, value: unknown) => { - if (!(value instanceof Map)) return value; - return { $type: "Map", value: Array.from(value.entries()) }; -}; - -const reviver = ( - key: string, - value: unknown & { - $type?: string; - value: Iterable; - } -) => { - const { $type } = (value || {}) as { $type?: string }; - return $type == "Map" && value.value - ? new Map(value.value) - : value; -}; - -export class DebuggerSettings implements SettingsProvider { - #settings: Settings = { - [SETTINGS_TYPE.GENERAL]: { - configuration: { - extensible: false, - description: "General", - nameEditable: false, - }, - items: new Map([ - [ - "Save Secrets", - { - name: "Save Secrets", - description: "Whether you wish to have secrets saved automatically", - value: true, - }, - ], - ]), - }, - [SETTINGS_TYPE.SECRETS]: { - configuration: { - extensible: true, - description: "Secrets", - nameEditable: true, - }, - items: new Map(), - }, - }; - - get values() { - return structuredClone(this.#settings); - } - - getItem(section: SETTINGS_TYPE, name: string): SettingValue | undefined { - return this.#settings[section].items.get(name); - } - - getSection(section: SETTINGS_TYPE): SettingsSection { - return this.#settings[section]; - } - - async save(settings: Settings): Promise { - const json = JSON.stringify(settings, replacer); - globalThis.localStorage.setItem(SETTINGS_KEY, json); - } - - async restore(): Promise { - const value = globalThis.localStorage.getItem(SETTINGS_KEY); - if (!value) return undefined; - this.#settings = JSON.parse(value, reviver); - } -} diff --git a/packages/breadboard-cli/src/index.ts b/packages/breadboard-cli/src/index.ts deleted file mode 100755 index 7bbb98f847b..00000000000 --- a/packages/breadboard-cli/src/index.ts +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env node - -// Note: We might hit this bug - https://github.com/npm/cli/issues/4149 - -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { debug } from "./commands/debug.js"; -import { mermaid } from "./commands/mermaid.js"; -import { makeGraph } from "./commands/make-graph.js"; -import { run } from "./commands/run.js"; -import { importGraph } from "./commands/import.js"; -import { bundle } from "./commands/bundle.js"; -import { proxy } from "./commands/proxy.js"; - -import { program } from "commander"; -import path from "path"; - -program.version("0.0.1"); - -program - .command("debug [file]") - .description( - "Starts a simple HTTP server that serves the visual-editor app, and outputs a URL that contains a link to a breadboard file that the user provided. Defaults to running on port 3000 (set the PORT environment variable to customize)" - ) - .option( - "-k, --kit ", - "The kit to use can be an NPM package name or a URL to the bundled kit (for heavy kits) or a kit manifest (for light kits)." - ) - .option("-n, --no-save", "Do not save the compiled graph to disk.") - .option( - "-o, --output ", - "The path where the boards will be output the board(s) to.", - process.cwd() - ) - .option("-w, --watch", "Watch the file for changes.") - .action(debug); - -program - .command("bundle [file]") - .description("Generates a deployable bundle.") - .option( - "-o, --output ", - "Sets the output directory of the compiled graph (current directory by default.)", - path.join( - process.cwd(), - `build-${new Date().toISOString().replaceAll(/\W/gim, "-")}` - ) - ) - .action(bundle); - -program - .command("import [url]") - .description("Imports an OpenAPI spec and creates a dedicated board.") - .option("-a, --api ", "Which API path / name will be exported.") - .option( - "-o, --output ", - "The path where the boards will be output the board(s) to (current directory by default.)", - process.cwd() - ) - .action(importGraph); - -program - .command("make [file]") - .description( - "Make a graph from a javascript file. Note:all the imports have to be resolvable from the current directory." - ) - .option( - "-o, --output ", - "The path where the boards will be output the board(s) to (current directory by default.)", - process.cwd() - ) - .option("-n, --no-save", "Do not save the compiled graph to disk.") - .option("-w, --watch", "Watch the file for changes.") - .option("-f, --format", "Format the BGL file.") - .action(makeGraph); - -program - .command("mermaid [file]") - .description( - "Watch a breadboard file and output the mermaid diagram when it changes." - ) - .option( - "-o, --output ", - "If compiling a graph in Typescript (.ts), you can control the output directory of the compiled graph (current directory by default.)", - process.cwd() - ) - .option("-w, --watch", "Watch the file for changes.") - .action(mermaid); - -program - .command("proxy") - .description("Starts a proxy server.") - .option("-c, --config ", "The path to the proxy configuration file.") - .option( - "-d, --dist ", - "The directory to serve for HTTP GET requests", - process.cwd() - ) - .option("-k, --kit ", "The kit to use.") - .option("-p, --port ", "The port to serve on.", "8080") - .option( - "-x, --proxy-node ", - "A node that will be passed to the breadboard proxy." - ) - .action(proxy); - -program - .command("run [file]") - .description("Run a graph.") - .option("-w, --watch", "Watch the file for changes.") - .option("-v, --verbose", "Output events and processing information.") - .option("-n, --no-save", "Do not write the compiled graph to disk.") - .option( - "-o, --output ", - "If compiling a graph in Typescript (.ts), you can control the output directory of the compiled graph (current directory by default.)", - process.cwd() - ) - .option("-k, --kit ", "The kit to use.") - .option("-p, --proxy ", "The Breadboard proxy to use.") - .option( - "-x, --proxy-node ", - "A node that will be passed to the breadboard proxy." - ) - .option( - "--input-file ", - "The path to a JSON file that represents the input to the graph." - ) - .option( - "-i, --input ", - "The JSON that represents the input to the graph." - ) - .action(run); - -program.parse(); - -// Allow developers to integrate with the CLI -export { debug, mermaid, makeGraph, run }; diff --git a/packages/breadboard-cli/tests/index.ts b/packages/breadboard-cli/tests/index.ts deleted file mode 100644 index 8d7e790e249..00000000000 --- a/packages/breadboard-cli/tests/index.ts +++ /dev/null @@ -1,378 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Board } from "@google-labs/breadboard"; -import test from "ava"; -import { ExecException, exec } from "child_process"; -import * as fs from "fs"; -import path from "path"; - -const packageDir = getPackageDir("@google-labs/breadboard-cli"); -console.debug("packageDir", packageDir); - -const dist = path.resolve(path.join(packageDir, "dist")); - -const cliPathJs = path.resolve(path.join(dist, "src", "index.js")); -console.assert(fs.existsSync(cliPathJs)); - -type ChildProcessCallback = { - error?: ExecException | null; - stdout: string; - stderr: string; -}; - -function getPackageDir(packageName: string) { - let packageDir = ""; - let found = false; - while (!found) { - const packagePath = path.join(packageDir, "package.json"); - if (fs.existsSync(packagePath)) { - const packageData = JSON.parse(fs.readFileSync(packagePath, "utf-8")); - if (packageData.name === packageName) { - found = true; - break; - } - } - packageDir = path.resolve(path.join(packageDir, "..")); - - if (packageDir === "/") { - throw new Error( - "Could not find package.json for @google-labs/breadboard-cli" - ); - } - } - return packageDir; -} - -function execCli(args = ""): Promise { - return new Promise((resolve, reject) => { - exec(`node "${cliPathJs}" ${args}`, (error, stdout, stderr) => { - if (error) { - reject({ error, stdout, stderr }); - } else { - resolve({ stdout, stderr }); - } - }); - }); -} - -function makeBoard(): Board { - const board: Board = new Board({ - title: "Echo", - description: "Echo cho cho cho ho o", - version: "0.0.3", - }); - const input = board.input({ - schema: { - type: "object", - properties: { - text: { - type: "string", - title: "Echo", - description: "What shall I say back to you?", - }, - }, - }, - }); - const output = board.output(); - input.wire("text", output); - return board; -} - -const testBoardData = JSON.parse(JSON.stringify(makeBoard())); - -const typescriptTestBoardContent = [ - 'import { Board } from "@google-labs/breadboard";', - // it appears toString on a function ommits types - makeBoard - .toString() - .replace( - `function ${makeBoard.name}() {`, - `function ${makeBoard.name}(): Board {` - ) - .replace(`const board = new Board({`, `const board: Board = new Board({`), - `const board: Board = ${makeBoard.name}();`, - `export default board;`, -].join("\n\n"); -console.debug( - [`${"```"}typescript board.ts`, typescriptTestBoardContent, `${"```"}`].join( - "\n" - ) -); - -const jsTestBoardContent = [ - 'import { Board } from "@google-labs/breadboard";', - makeBoard.toString(), - `const board = ${makeBoard.name}();`, - `export default board;`, -].join("\n\n"); - -console.debug( - [`${"```"}javascript board.js`, jsTestBoardContent, `${"```"}`].join("\n") -); - -const tempDir = path.join(path.join(packageDir, "temp")); -const testDataDir = path.resolve(path.join(tempDir, "data")); -const originalBoardPath = path.join(testDataDir, "echo.json"); - -const relativeBoardPath = path.relative(process.cwd(), originalBoardPath); -const absoluteBoardPath = path.resolve(relativeBoardPath); - -const filenameWithSpaces = path.resolve( - path.join(testDataDir, "test board.json") -); - -const filenameWithURLencodingSpaces = path.resolve( - path.join(testDataDir, "test%20board.json") -); - -const directoryWithSpaces = path.resolve( - path.join(testDataDir, "test folder", "board.json") -); - -const typescriptBoardPath = path.resolve(path.join(testDataDir, "ts_board.ts")); -const jsBoardPath = path.resolve(path.join(testDataDir, "js_board.js")); -const testBoardDataContent = JSON.stringify(testBoardData, null, 2); - -const testFiles: { - path: string; - content: string; -}[] = [ - ...[ - originalBoardPath, - filenameWithSpaces, - filenameWithURLencodingSpaces, - directoryWithSpaces, - ].map((p) => { - return { - path: p, - content: testBoardDataContent, - }; - }), - { - path: path.resolve(typescriptBoardPath), - content: typescriptTestBoardContent, - }, - { - path: path.resolve(jsBoardPath), - content: jsTestBoardContent, - }, -]; - -////////////////////////////////////////////////// - -test.before(() => { - testFiles.forEach((p) => { - console.debug( - ["Writing", `${p.content.length} characters to`, p.path].join("\t") - ); - fs.mkdirSync(path.dirname(p.path), { recursive: true }); - fs.writeFileSync(p.path, p.content); - }); -}); - -test.after.always(() => { - console.debug("Cleaning up test files"); - testFiles.forEach((p) => { - console.debug(); - const filename = path.basename(p.path); - const dirname = path.dirname(p.path); - const filenameWithoutExtension = filename.split(".")[0]; - - console.debug([`Searching for`, p.path].join("\t")); - - ["json", "ts", "js"] - .map((ext) => [ - path.resolve(path.join(dirname, `${filenameWithoutExtension}.${ext}`)), - path.resolve( - path.join(packageDir, `${filenameWithoutExtension}.${ext}`) - ), - ]) - .flat() - .forEach((testDirPath) => { - if (fs.existsSync(testDirPath)) { - console.debug(["Removing", testDirPath].join("\t")); - fs.rmSync(testDirPath); - } - }); - }); - fs.rmSync(testDataDir, { recursive: true }); -}); - -////////////////////////////////////////////////// -test("all test files exist", (t) => { - testFiles.forEach((p) => { - t.true(fs.existsSync(p.path)); - t.true(fs.readFileSync(p.path).length > 0); - }); -}); - -////////////////////////////////////////////////// -test("relative path is relative and valid", (t) => { - console.debug("relativeBoardPath", relativeBoardPath); - t.false(relativeBoardPath == path.resolve(relativeBoardPath)); - t.true(fs.existsSync(relativeBoardPath)); -}); - -test("calling CLI with no parameters shows usage text", async (t) => { - const expected = "Usage: index [options] [command]"; - try { - await execCli(); - } catch (error: unknown) { - const output = error as ChildProcessCallback; - t.assert(output.stderr); - if (output.stderr) { - t.true(output.stderr.length > expected.length); - t.true(output.stderr.includes(expected)); - } - } -}); - -test("'mermaid' command produces mermaid diagram from relative path to board.json", async (t) => { - const commandString = ["mermaid", `"${relativeBoardPath}"`].join(" "); - const output = await execCli(commandString); - t.assert(output.stdout); - t.true(output.stdout.length > 0); - t.true(output.stdout.includes("graph TD")); -}); - -test("'mermaid' command produces mermaid diagram from absolute path to board.json", async (t) => { - t.false(absoluteBoardPath.startsWith("tests")); - t.true(fs.existsSync(absoluteBoardPath)); - - const commandString = ["mermaid", `"${absoluteBoardPath}"`].join(" "); - const output = await execCli(commandString); - t.assert(output.stdout); - t.true(output.stdout.length > 0); - t.true(output.stdout.includes("graph TD")); -}); - -////////////////////////////////////////////////// - -test("filename does contain spaces", (t) => { - t.true(path.basename(filenameWithSpaces).includes(" ")); -}); - -test("can handle a relative file with spaces in the file name", async (t) => { - const relativePath = path.relative(process.cwd(), filenameWithSpaces); - t.true(relativePath.includes(" ")); - t.true(fs.existsSync(filenameWithSpaces)); - - const commandString = ["mermaid", `"${relativePath}"`].join(" "); - const output = await execCli(commandString); - t.true(output.stdout.length > 0); - t.true(output.stdout.includes("graph TD")); -}); - -test("can handle an absolute file with spaces in the name", async (t) => { - const commandString = ["mermaid", `"${filenameWithSpaces}"`].join(" "); - const output = await execCli(commandString); - t.true(output.stdout.length > 0); - t.true(output.stdout.includes("graph TD")); -}); - -test("can handle an absolute file with text that decodeURIComponent might resolve in the name", async (t) => { - const commandString = ["mermaid", `"${filenameWithURLencodingSpaces}"`].join( - " " - ); - const output = await execCli(commandString); - t.true(output.stdout.length > 0); - t.true(output.stdout.includes("graph TD")); -}); - -////////////////////////////////////////////////// - -test("directory name with spaces does contain spaces", (t) => { - t.true(path.dirname(directoryWithSpaces).includes(" ")); -}); - -test("board file exists in dictory with spaces in the name", (t) => { - t.true(fs.existsSync(directoryWithSpaces)); -}); - -test("can handle a relative path with spaces in the directory name", async (t) => { - const relativePath = path.relative(process.cwd(), directoryWithSpaces); - t.true(relativePath.includes(" ")); - t.true(fs.existsSync(directoryWithSpaces)); - - const commandString = ["mermaid", `"${relativePath}"`].join(" "); - const output = await execCli(commandString); - t.true(output.stdout.length > 0); - t.true(output.stdout.includes("graph TD")); -}); - -test("can handle an absolute path with spaces in the directory name", async (t) => { - const commandString = ["mermaid", `"${directoryWithSpaces}"`].join(" "); - const output = await execCli(commandString); - t.true(output.stdout.length > 0); - t.true(output.stdout.includes("graph TD")); -}); - -////////////////////////////////////////////////// - -test("can make a graph from a typescript file", async (t) => { - const tscCommand = [ - "npx", - "-y", - "tsc", - "--target ES2022", - "--module NodeNext", - // TODO(aomarks) There's a glob typing mismatch error. - "--skipLibCheck", - `--outDir "${path.dirname(typescriptBoardPath)}"`, - `"${typescriptBoardPath}"`, - ].join(" "); - await new Promise((resolve, reject) => { - exec(tscCommand, (error, stdout, stderr) => { - if (error) { - reject({ error, stdout, stderr }); - } else { - resolve({ stdout, stderr }); - } - }); - }); - - const jsPath = typescriptBoardPath.replace(".ts", ".js"); - t.true(fs.existsSync(jsPath)); - - const commandString = ["make", `"${jsPath}"`, "-n"].join(" "); - const output = await execCli(commandString); - t.true(output.stdout.length > 0); -}); - -////////////////////////////////////////////////// - -test("can make a graph from a javascript file", async (t) => { - const commandString = ["make", `"${jsBoardPath}"`, "-n"].join(" "); - const output = await execCli(commandString); - t.true(output.stdout.length > 0); -}); - -test("can run a json board", async (t) => { - const inputData = { - text: "Hi", - }; - const commandString = [ - "run", - `"${absoluteBoardPath}"`, - `--input "${JSON.stringify(inputData).replaceAll('"', '\\"')}"`, - ].join(" "); - const output = await execCli(commandString); - t.true(output.stdout.length > 0); - - let resultString = output.stdout; - - // remove ANSI escape codes - // eslint-disable-next-line no-control-regex - resultString = resultString.replace(/\u001b\[[0-9]{1,2}m/g, ""); - - // replace single quotes with double quotes - resultString = resultString - .replace(/(\w+)(?=:)/g, '"$1"') - .replace(/:\s*'([^']+)'/g, ': "$1"'); - - t.deepEqual(JSON.parse(resultString), inputData); -}); diff --git a/packages/breadboard-cli/tests/proxy.config.json b/packages/breadboard-cli/tests/proxy.config.json deleted file mode 100644 index 8272e353fc4..00000000000 --- a/packages/breadboard-cli/tests/proxy.config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "kits": ["@google-labs/core-kit"], - "proxy": ["fetch"] -} diff --git a/packages/breadboard-cli/tsconfig.json b/packages/breadboard-cli/tsconfig.json deleted file mode 100644 index 921d73e2acc..00000000000 --- a/packages/breadboard-cli/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "outDir": "./dist", - "moduleResolution": "NodeNext", - "resolveJsonModule": true - }, - "include": ["src/**/*", "tests/**/*"], - "exclude": ["dist"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/breadboard-cli/vite.config.ts b/packages/breadboard-cli/vite.config.ts deleted file mode 100644 index 8946b2c9258..00000000000 --- a/packages/breadboard-cli/vite.config.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { defineConfig } from "vitest/config"; -import { fileURLToPath } from "url"; -import { createRequire } from "module"; -import { dirname, join } from "path"; - -// Carry through the visual-editor public dir as the public dir for the -// debugger here. It's essentially a passthrough. -let breadboardWebPublic: boolean | string = false; -// @ts-expect-error 2274 -if (import.meta.resolve) { - const publicPath = import.meta.resolve("@breadboard-ai/visual-editor/public"); - breadboardWebPublic = fileURLToPath(publicPath); -} else { - const require = createRequire(import.meta.url); - const breadboardWebIndex = require.resolve("@breadboard-ai/visual-editor"); - breadboardWebPublic = join(dirname(breadboardWebIndex), "..", "public"); -} - -export default defineConfig({ - optimizeDeps: { - include: [ - "@breadboard-ai/visual-editor", - "@google-labs/breadboard", - "@google-labs/core-kit", - "@google-labs/template-kit", - "commander", - "esbuild", - "serve", - "vite", - "yaml", - ], - }, - build: { - lib: { - entry: { - // TODO: These are just variants of the visual-editor entry points; we - // could (and possibly should) unify them. - index: "./index.html", - preview: "./preview.html", - }, - name: "Breadboard Debugger Runtime", - formats: ["es"], - }, - outDir: "../../dist/debugger", - target: "esnext", - }, - root: "src/debugger", - publicDir: breadboardWebPublic, -}); diff --git a/packages/breadboard-python/.gitignore b/packages/breadboard-python/.gitignore deleted file mode 100644 index 9fe36762c47..00000000000 --- a/packages/breadboard-python/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.egg-info -*/build/ -*/dist/ \ No newline at end of file diff --git a/packages/breadboard-python/breadboard_colab/build/lib/colab.py b/packages/breadboard-python/breadboard_colab/build/lib/colab.py deleted file mode 100644 index a3016fd870f..00000000000 --- a/packages/breadboard-python/breadboard_colab/build/lib/colab.py +++ /dev/null @@ -1,98 +0,0 @@ -from io import StringIO -import json -import sys - -import logging -from google.colab import output -from IPython import display - - - -def run_python(data): - try: - # Extract code input - code = data["$code"] - data.pop("$code") - - old_stdout = sys.stdout - redirected_output = sys.stdout = StringIO() - - previous_globals = dict(globals() | data) - globals().update(data) - exec_result = exec(code, globals(), globals()) - - sys.stdout = old_stdout - - current_globals = dict(previous_globals | globals()) - changed_globals = {} - for k in current_globals: - if ( - k not in previous_globals - or current_globals[k] != previous_globals[k] - or k in data - ): - try: - json.dumps(current_globals[k]) - changed_globals[k] = current_globals[k] - except TypeError: - logging.debug( - "Skipping output variable that's not json serializable:" - f" {current_globals[k]}" - ) - - res = changed_globals | { - "result": exec_result, - "stdout": redirected_output.getvalue(), - } - logging.debug("Exec result: %s", res) - return json.dumps(res) - except Exception as e: - return json.dumps([{"error": f"Python Failure: {e}"}]) - - - -def start_breadboard_iframe( - breadboard_url: str = "https://breadboard-ai.web.app", -): - output.register_callback('breadboard_run_python', run_python) - output.eval_js(""" -function parse_python_output(python_output) { - let a = python_output.replace("\\\\\\\\", "\\\\").replace("\\\\'", "'"); - a = a.replace('\\\\"', '"'); - return a; -} -const channel = new MessageChannel(); - const out = channel.port2; - - const processMessage = (type, data) => { - if (type === "proxy" && data.node.type === "runPython") { - - google.colab.kernel.invokeFunction('breadboard_run_python', [data.inputs], {}).then(resp => { - const resp_body = JSON.parse(parse_python_output(resp.data["text/plain"].slice(1, -1))); - out.postMessage(["proxy", {outputs: {...{ context: data.inputs }, ...resp_body }}]); - }); - } else { - out.postMessage([ - "error", { error: "unknown node, not sure what to do" } - ]) - } - } - - out.addEventListener("message", (evt) => { - processMessage(... evt.data); - }); - out.start(); - - window.addEventListener("message", (evt) => { - if (evt.data !== "letsgo") { - return; - } - const iframe = document.getElementById("breadboard_iframe").contentWindow; - iframe.postMessage(evt.data, evt.origin, [ channel.port1 ]); - }); - """) - target_url = breadboard_url - display.display_html( - f'', raw=True - ) diff --git a/packages/breadboard-python/breadboard_colab/pyproject.toml b/packages/breadboard-python/breadboard_colab/pyproject.toml deleted file mode 100644 index 313535c83f5..00000000000 --- a/packages/breadboard-python/breadboard_colab/pyproject.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "breadboard_colab" -requires-python = ">= 3.8" -version = "0.0.3" - -description = "A Python library for running Breadboard on Colab" -authors = [ - {name = "Kevin Xiao", email = "xiaok10003@gmail.com"}, -] -keywords = ["breadboard", "colab"] - - -dependencies = [ - "google", - "google-api-core" -] \ No newline at end of file diff --git a/packages/breadboard-python/breadboard_colab/src/breadboard_colab.py b/packages/breadboard-python/breadboard_colab/src/breadboard_colab.py deleted file mode 100644 index 2a77bb2bcaa..00000000000 --- a/packages/breadboard-python/breadboard_colab/src/breadboard_colab.py +++ /dev/null @@ -1,99 +0,0 @@ -from io import StringIO -import json -import sys - -import logging -from google.colab import output -from IPython import display - - -def run_python(data): - try: - # Extract code input - code = data["$code"] - data.pop("$code") - - old_stdout = sys.stdout - redirected_output = sys.stdout = StringIO() - - previous_globals = dict(globals() | data) - globals().update(data) - exec_result = exec(code, globals(), globals()) - - sys.stdout = old_stdout - - current_globals = dict(previous_globals | globals()) - changed_globals = {} - for k in current_globals: - if ( - k not in previous_globals - or current_globals[k] != previous_globals[k] - or k in data - ): - try: - json.dumps(current_globals[k]) - changed_globals[k] = current_globals[k] - except TypeError: - logging.debug( - "Skipping output variable that's not json serializable:" - f" {current_globals[k]}" - ) - - res = changed_globals | { - "result": exec_result, - "stdout": redirected_output.getvalue(), - } - logging.debug("Exec result: %s", res) - return json.dumps(res) - except Exception as e: - return json.dumps([{"error": f"Python Failure: {e}"}]) - - -def start_breadboard_iframe( - breadboard_url: str = "https://breadboard-ai.web.app", -): - output.register_callback('breadboard_run_python', run_python) - output.eval_js(""" -function parse_python_output(python_output) { - let parsed_output = python_output.replace(/\\\\\\\\|\\\\'|\\\\"/g,function(match) { - if (match=="\\\\\\\\") return "\\\\"; - if (match=="\\\\'") return "\"; - if (match=='\\\\"') return '"'; - }) - return parsed_output; -} -const channel = new MessageChannel(); - const out = channel.port2; - - const processMessage = (type, data) => { - if (type === "proxy" && data.node.type === "runPython") { - - google.colab.kernel.invokeFunction('breadboard_run_python', [data.inputs], {}).then(resp => { - const resp_body = JSON.parse(parse_python_output(resp.data["text/plain"].slice(1, -1))); - out.postMessage(["proxy", {outputs: {...{ context: data.inputs }, ...resp_body }}]); - }); - } else { - out.postMessage([ - "error", { error: "unknown node, not sure what to do" } - ]) - } - } - - out.addEventListener("message", (evt) => { - processMessage(... evt.data); - }); - out.start(); - - window.addEventListener("message", (evt) => { - if (evt.data !== "colab_iframe") { - return; - } - const iframe = document.getElementById("breadboard_iframe").contentWindow; - iframe.postMessage(evt.data, evt.origin, [ channel.port1 ]); - }); - """) - target_url = breadboard_url.strip("/") + "/iframe.html?configId=colab_iframe" - display.display_html( - f'', raw=True - ) diff --git a/packages/breadboard-python/breadboard_python/.eslintrc b/packages/breadboard-python/breadboard_python/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/breadboard-python/breadboard_python/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/breadboard-python/breadboard_python/LICENSE b/packages/breadboard-python/breadboard_python/LICENSE deleted file mode 100644 index d6456956733..00000000000 --- a/packages/breadboard-python/breadboard_python/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/packages/breadboard-python/breadboard_python/README.md b/packages/breadboard-python/breadboard_python/README.md deleted file mode 100644 index b190a768a65..00000000000 --- a/packages/breadboard-python/breadboard_python/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# Breadboard Oython - -Breadboard Python is a library that allows developers to define Breadboards with Python. - -Each Breadboard can be serialized into a JSON graph. An executor can take this graph and run it. - -The available executors are currently breadboard-web, and breadboard-cli. - -# Installation - -Install with pip: - -``` -pip install breadboard_python -``` - -# Getting started - -1. Define a Board in a python file -2. Save the Board to packages/breadboard-web/src/boards/ directory. -3. `cd packages/breadboard-web` -4. `npm i` -5. `npm run build` -6. `npm run dev` -7. Access web portal on localhost:5173 - -# Usage - -Here's a starter board: - -```python -from breadboard_python.main import Board, Field, SchemaObject - -class InputSchema(SchemaObject): - input1: str = Field(description="This is a description of input1.", required=True) - -class OutputSchema(SchemaObject): - output1: str = Field(description="This is a description of output1.) - - -class Echo(Board[InputSchema, OutputSchema]): - title = "Echo" - description = "A trivial Board that takes text as input, and outputs back the same text." - version = "1.0.0" - - def describe(self, input, output) -> None: - output(output1=input.input1) -``` - -There are 4 steps to do when defining a Board: - -1. Define input and output schemas by inheriting SchemaObject. -2. Creating a child class of Board, passing in the input and output schema classes -3. Populating the metadata fields: "title", "description", and "version". -4. Implementing the `describe(self, input, output)` method, which defines sub-Boards and describes how they wire into each other. - -## Defining Input and Output Schemas - -Input and Output schemas should inherit from the SchemaObject class, which is a wrapper around Pydantic. -Field metadata can be populated in the Field constructor. - -Example: - -```python -class InputSchema(SchemaObject): - input1: str = Field(description="This is a description of input1.", required=True) - # By default, required is False. - input2: List[int] = Field([], description="Another description.") -``` - -If an InputSchema or OutputSchema is not provided, they will default to Any. -In this example, the Board input/output signature simply defaults ot Any, Any - -```python -class ExampleBoard(Board): - description = "This Board has a signature of [Any, Any]." -``` - -## Defining a Board - -The Input and Output schemas should be passed into the generic Board arguments when inheriting from Board. - -```python -class ExampleBoard(Board[SomeInputSchema, SomeOutputSchema]): - title = "ExampleBoard" - description = "Some description of what the Board does." - version = "0.0.1" -``` - -## Implementing describe - -The describe function has two parameters: input and output, which represent the input and output nodes. - -Here, component Boards are defined, and they are wired to and from each other. -Wiring is one-directional, and is done by making a call to the component. -For instance, in this example: - -```python -class ExampleBoard(Board): - def describe(self, input, output): - self.componentA = SomeBoard(arg1="blar", arg2=input.text) - self.componentB = AnotherBoard(arg3=self.componentA.output1) - output(self.componentB) -``` - -The "text" field from the input is fed into componentA's "arg2" input field. -The "output1" output field from componentA is fed into componentB's "arg3" input field. -Finally, all of componentB's output fields are fed into output under the same names. - -```mermaid -%%{init: 'themeVariables': { 'fontFamily': 'Fira Code, monospace' }}%% -graph TD; -input["input
    id='input'"] -- "text->arg2" --> componentA["SomeBoard
    id='componentA'"] -componentA["SomeBoard
    id='componentA'"] -- "output1->arg3" --> componentB["AnotherBoard
    id='componentB'"] -componentB["AnotherBoard
    id='componentB'"] --> output["output
    id='output'"] -classDef input stroke:#3c78d8,fill:#c9daf8ff,color:#000 -classDef output stroke:#38761d,fill:#b6d7a8ff,color:#000 -classDef componentA stroke:#a64d79,fill:#ead1dcff,color:#000 -classDef componentB stroke:#a64d79,fill:#ead1dcff,color:#000 -``` - -## Importing functions from Javascript - -Javascript kits are each a collection of handlers and are published to npm. Javascript handlers can be thought of as Boards. -To utilize Javascript kits, you can import them with breadboard_python.import_nodes.require. - -For instance: - -```python -from breadboard_python.import_nodes import require -Templates = require("@google-labs/template-kit") - -class ExampleBoard(Board): - def describe(self, input, output) -> None: - self.template = Templates.promptTemplate(template="Input1: {{input1}}", input1=input.input1) - output(text=self.template.prompt) -``` - -## Defining functions in Python - -Coming Soon. diff --git a/packages/breadboard-python/breadboard_python/pyproject.toml b/packages/breadboard-python/breadboard_python/pyproject.toml deleted file mode 100644 index dbfbb2f0dbb..00000000000 --- a/packages/breadboard-python/breadboard_python/pyproject.toml +++ /dev/null @@ -1,20 +0,0 @@ -[project] -name = "breadboard_python" -requires-python = ">= 3.8" -version = "0.1.0" - -description = "A Python library for defining Breadboards." -authors = [ - {name = "Kevin Xiao", email = "xiaok10003@gmail.com"}, -] -keywords = ["breadboard"] - - -dependencies = [ - "pydantic", - "javascript", - "jsonref", - "json_fix", - "prettydiff", - "cloudpickle", -] \ No newline at end of file diff --git a/packages/breadboard-python/breadboard_python/requirements.txt b/packages/breadboard-python/breadboard_python/requirements.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/breadboard-python/breadboard_python/src/__init__.py b/packages/breadboard-python/breadboard_python/src/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/breadboard-python/breadboard_python/src/accumulating_context.py b/packages/breadboard-python/breadboard_python/src/accumulating_context.py deleted file mode 100644 index 5f63d802524..00000000000 --- a/packages/breadboard-python/breadboard_python/src/accumulating_context.py +++ /dev/null @@ -1,48 +0,0 @@ - -from breadboard_python.main import Board, Field, SchemaObject -from breadboard_python.import_node import require -import json -from typing import Optional, Union - -Core = require("@google-labs/core-kit") -Templates = require("@google-labs/template-kit") - -class InputSchema(SchemaObject): - text: str = Field(description="User: type here to chat with the assistant") - generator: str = Field("text-generator.json", description="Generator: Text generator to use") - -class OutputSchema(SchemaObject): - text: str = Field(title="Assistant", description="Assistant: Assistant's response in the conversation with the user", required=True) - - -class AccumulatingContext(Board[InputSchema, OutputSchema]): - title = "Accumulating Context (Python)" - description = 'An example of a board that implements a multi-turn experience: a very simple chat bot that accumulates context of the conversations. Tell it "I am hungry" or something like this and then give simple replies, like "bbq". It should be able to infer what you\'re asking for based on the conversation context. All replies are pure hallucinations, but should give you a sense of how a Breadboard API endpoint for a board with cycles looks like.' - version = "0.0.2" - - type = "accumulating-context" - - def describe(self, input, output): - self.prompt = Templates.promptTemplate( - id="assistant", - template="This is a conversation between a friendly assistant and their user. You are the assistant and your job is to try to be helpful, empathetic, and fun.\n{{context}}\n\n== Current Conversation\nuser: {{question}}\nassistant:", - context="", - ) - self.conversationMemory = Core.append( - accumulator="\n== Conversation History", - ) - - self.prompt(question=input.text) - self.conversationMemory(user=input.text) - self.conversationMemory(accumulator=self.conversationMemory.accumulator) - self.prompt(context=self.conversationMemory.accumulator) - generator = Core.invoke(id="generator", path=input.generator, text=self.prompt.prompt) - self.conversationMemory(assistant=generator.text) - output(text=generator.text) - input(output) - -if __name__ == "__main__": - import sys - a = AccumulatingContext() - with open(sys.argv[1], "w") as f: - json.dump(a, f, indent=2) diff --git a/packages/breadboard-python/breadboard_python/src/adhoc.py b/packages/breadboard-python/breadboard_python/src/adhoc.py deleted file mode 100644 index fad6096a88e..00000000000 --- a/packages/breadboard-python/breadboard_python/src/adhoc.py +++ /dev/null @@ -1,106 +0,0 @@ -from .main import Board -import dis -import sys -from contextlib import contextmanager -from typing import Any -import builtins as builtin -import json -import cloudpickle -import base64 -import sys - -def get_function_calls(func, built_ins=False): - # the used instructions - ins = list(dis.get_instructions(func))[::-1] - - # dict for function names (so they are unique) - names = {} - - # go through call stack - for i, inst in list(enumerate(ins))[::-1]: - # find last CALL_FUNCTION - - print(inst) - if inst.opname == "CALL" or inst.opname == "CALL_FUNCTION_EX": - - # function takes ins[i].arg number of arguments - ep = i + inst.arg + 1 + (2 if inst.opname[13:16] == "_KW" else 1) - - # LOAD that loaded this function - entry = ins[ep] - print(f"KEX: {entry}") - - # ignore list comprehensions / ... - name = str(entry.argval) - if "." not in name and entry.opname == "LOAD_GLOBAL" and (built_ins or not hasattr(builtin, name)): - # save name of this function - names[name] = True - - # reduce this CALL_FUNCTION and all its paramters to one entry - ins = ins[:i] + [entry] + ins[ep + 1:] - - return sorted(list(names.keys())) - -import inspect -ALL_HANDLERS = {} -def breadboard_node(func): - print(get_function_calls(func)) - print(inspect.signature(func).parameters) - print(inspect.signature(func).return_annotation) - #code = inspect.getsource(func) - pickled_code = cloudpickle.dumps(func) - pickled_code = base64.b64encode(pickled_code).decode('ascii') - print(pickled_code) - - # get the input/output schema of the function. set it to a master registry. - # replace all function calls with decorated ones. - class FuncBoard(Board): - title = "func.get_name()" - type = "runPython" - description = "func.get_docstring()" - _is_node = True - _source_code = None - _pickled_code = pickled_code - _python_version = '.'.join(str(x) for x in sys.version_info[:3]) - def describe(self, input, output): - pass - - def get_configuration(self): - config = super().get_configuration() - if "code" in config: - raise Exception("Code is already populated.") - config["code"] = self._source_code - config["pickle"] = self._pickled_code - config["python_version"] = self._python_version - return config - - return FuncBoard - -def child_function1(): - return 3 - - -def child_function2(key: str): - return 3 - - - -@breadboard_node -def master_function(key: str, value: Any) -> int: - output = 0 - if value: - output += child_function1() - output += child_function2(key=key) - output += child_function2(key) - output += child_function2(**key) - return output - -class TestBoard(Board): - def describe(self, input, output): - self.node = master_function(key="key1", value=input.field1) - output(self.node) - - -#print(get_function_calls(master_function)) -#a = TestBoard() -#print(json.dumps(a, indent=2)) \ No newline at end of file diff --git a/packages/breadboard-python/breadboard_python/src/chat_gpt_3_5_turbo.py b/packages/breadboard-python/breadboard_python/src/chat_gpt_3_5_turbo.py deleted file mode 100644 index d79874e2e3b..00000000000 --- a/packages/breadboard-python/breadboard_python/src/chat_gpt_3_5_turbo.py +++ /dev/null @@ -1,246 +0,0 @@ -from main import Board, Field, SchemaObject, List, AttrDict -import json -from typing import Optional, Union - -from import_node import require -Starter = require("@google-labs/llm-starter") -Nursery = require("@google-labs/node-nursery-web") - -class TransformOutput(AttrDict): - stream: SchemaObject = Field(description="Mocked stream field") -class ChunkTransformerOutput(SchemaObject): - chunk: str = Field(description="The result of the Jsonata expression", title="result", required=True) -class ChunkTransformerInput(SchemaObject): - chunk: Union[str, SchemaObject] = Field(description="The JSON object to evaluate", title="json", required=True) - -class Nursery_transformStream(Board): - type = "transformStream" - def describe(self, input): - # TODO: Why doesn't this ever run? Load needs to happen in initializer. - raise Exception("YOoo") - - self.output = TransformOutput() - return self.output - -class ChunkTransformer(Board[ChunkTransformerInput ,ChunkTransformerOutput]): - title = None - description = None - version = None - type = "board" - def describe(self, input): - transformCompletion = Starter.jsonata( - id="transformCompletion", - expression='choices[0].delta.content ? choices[0].delta.content : ""', - json=input.chunk - ) - self.output = AttrDict() - self.output.chunk = transformCompletion.result - return self.output - - -toolsExample = [ - { - "name": "The_Calculator_Recipe", - "description": - "A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.", - "parameters": { - "type": "object", - "properties": { - "text": { - "type": "string", - "description": "Ask a math question", - }, - }, - "required": ["text"], - }, - }, - { - "name": "The_Search_Summarizer_Recipe", - "description": - "A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.", - "parameters": { - "type": "object", - "properties": { - "text": { - "type": "string", - "description": "What would you like to search for?", - }, - }, - "required": ["text"], - }, - }, -] -contextExample = [ - { - "role": "system", - "content": "You are a pirate. Please talk like a pirate.", - }, -] - -FORMAT_PARAMETERS_EXPRESSION = """( - $context := $append( - context ? context, [ - { - "role": "user", - "content": text - } - ]); - OPENAI_API_KEY ? text ? { - "headers": { - "Content-Type": "application/json", - "Authorization": "Bearer " & OPENAI_API_KEY - }, - "body": { - "model": "gpt-3.5-turbo-1106", - "messages": $context, - "stream": useStreaming, - "temperature": 1, - "top_p": 1, - "tools": tools ? [tools.{ "type": "function", "function": $ }], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "stream": useStreaming, - "context": $context - } : { - "$error": "`text` input is required" - } : { - "$error": "`OPENAI_API_KEY` input is required" - } - )""" - -class InputSchema(SchemaObject): - text: str = Field( - description="The text to generate", - examples=["What is the correct term for the paddle in cricket?"], - required=True, - ) - - tools: List[str] = Field( - '[]', - description="An array of functions to use for tool-calling", - examples=[json.dumps(toolsExample, indent=2)], - ) - - context: List[SchemaObject] = Field( - '[]', - title="Context", - description="An array of messages to use as conversation context", - examples= [json.dumps(contextExample, indent=2)], - ) - - useStreaming: bool = Field( - 'false', - title="Stream", - description="Whether to stream the output", - ) - -class TextOutputSchema(SchemaObject): - text: str = Field(title="Text", description="The generated text") - context: List[str] = Field(title="Context", description="The conversation context") - -class ToolOutputSchema(SchemaObject): - toolCalls: SchemaObject = Field(title="Tool Calls", description="The generated tool calls") - context: List[str] = Field(title="Context", description="The conversation context") - -class StreamOutputSchema(SchemaObject): - stream: SchemaObject = Field(title="Stream", format="stream", description="The generated text", type="object") - -class OutputSchema(SchemaObject): - textOutput: TextOutputSchema - toolCallsOutput: ToolOutputSchema - streamOutput: StreamOutputSchema - -class OpenAiGpt_3_5_Turbo(Board[InputSchema, OutputSchema]): - # Metadata - title = "OpenAI GPT-3.5-turbo" - description = "This board is the simplest possible invocation of OpenAI's GPT-3.5 API to generate text." - version = "0.0.2" - - def init(self) -> None: - self.formatParameters = Starter.jsonata( - id="formatParameters", - expression=FORMAT_PARAMETERS_EXPRESSION, - raw=True, - OPENAI_API_KEY=Starter.secrets(keys=["OPENAI_API_KEY"]), - ) - self.fetch = Starter.fetch( - id="callOpenAI", - url="https://api.openai.com/v1/chat/completions", - method="POST", - ) - self.getResponse = Starter.jsonata( - id="getResponse", - expression="""choices[0].message.{ - "text": $boolean(content) ? content, - "tool_calls": tool_calls.function ~> | $ | { "args": $eval(arguments) }, "arguments" | - }""", - raw=True, - #json=UNFILLED, - ) - self.getNewContext = Starter.jsonata( - id="getNewContext", - expression="$append(messages, response.choices[0].message)", - #messages=UNFILLED - ) - - def describe(self, input: InputSchema, output: OutputSchema) -> OutputSchema: - self.init() - - formatParameters = self.formatParameters(input) - self.fetch = self.fetch(formatParameters) - self.getResponse = self.getResponse(json=self.fetch.response) - self.getNewContext = self.getNewContext(messages=self.formatParameters.context) - self.streamTransform = Nursery.transformStream(board=ChunkTransformer, stream=self.fetch) - - output(textOutput=AttrDict(text=self.getResponse.text, context=self.getNewContext.result)) - output(toolCallsOutput=AttrDict(toolCalls=self.getResponse.tool_calls, context=self.getNewContext.result)) - output(streamOutput=AttrDict(**{"*":self.streamTransform})) - -print("Starting") - -a = OpenAiGpt_3_5_Turbo() -print(json.dumps(a, indent=2)) - -with open("output.json", "w") as f: - json.dump(a, f, indent=2) - -# Testing code. -def sort_fun(obj): - if isinstance(obj, list): - if len(obj) > 0 and isinstance(obj[0], tuple): - for element in obj: - if element[0] == "id": - return element[1] - return obj - return obj - -def ordered(obj): - if isinstance(obj, dict): - a = sorted([(k, ordered(v)) for k, v in obj.items()], key=sort_fun) - return a - if isinstance(obj, list): - return sorted([ordered(x) for x in obj], key=sort_fun) - else: - return obj - -def revert_back(obj): - if isinstance(obj, list): - if len(obj) > 0 and isinstance(obj[0], tuple): - return {k: revert_back(v) for k, v in obj} - else: - return [revert_back(x) for x in obj] - if isinstance(obj, dict): - raise Exception("Very unexpected") - else: - return obj - - -from prettydiff import print_diff -comparison_path = "/usr/local/google/home/kevxiao/breadboard/packages/breadboard-web/public/graphs/openai-gpt-35-turbo.json" -with open(comparison_path) as f: - expected = revert_back(ordered(json.load(f))) - -actual = revert_back(ordered(json.loads(json.dumps(a)))) -print_diff(actual, expected) -print(type(expected)) \ No newline at end of file diff --git a/packages/breadboard-python/breadboard_python/src/coffeebot.py b/packages/breadboard-python/breadboard_python/src/coffeebot.py deleted file mode 100644 index cbdfaaf7953..00000000000 --- a/packages/breadboard-python/breadboard_python/src/coffeebot.py +++ /dev/null @@ -1,150 +0,0 @@ - -from breadboard_python.main import Board, Field, SchemaObject -from breadboard_python.import_node import require -from breadboard_python.adhoc import breadboard_node -import json -from typing import Optional, Union, Callable, List - -Core = require("@google-labs/core-kit") -Templates = require("@google-labs/template-kit") - - -class Tool(SchemaObject): - name: str - boardPath: str - -class BoardCallerInput(SchemaObject): - text: str - context: str - tools: List[Tool] - -class BoardCallerOutput(SchemaObject): - text: str - context: str - -class BoardCaller(Board[BoardCallerInput, BoardCallerOutput]): - type = "board-caller" - def describe(self, input, output): - self.caller = Core.invoke(path=input.tools) - output(self.caller) - - - -class FunctionCallInput(SchemaObject): - text: str - context: str - tools: List[Tool] - -class FunctionCallOutput(SchemaObject): - text: str - context: str - -class HandleFunctionCall(Board[FunctionCallInput, FunctionCallOutput]): - type = "function-call" - def describe(self, input, output): - #self.boardCaller = BoardCaller(input) - self.caller = Core.invoke(path="board-caller.json", text=input.text, context=input.context, tools=input.tools) - output(input) - - -class ChatBotInput(SchemaObject): - text: str - post_process: Optional[str] - prompt: str - -class ChatBotOutput(SchemaObject): - pass - -class ChatBot(Board[ChatBotInput, ChatBotOutput]): - type = "chat-bot" - def describe(self, input, output): - self.prompt = Templates.promptTemplate( - template="This is a conversation between a friendly assistant and their user. You are the assistant and your job is to try to be helpful, empathetic, and fun.\n{{context}}\n\n== Current Conversation\nuser: {{question}}\nassistant:", - context="", - ) - self.conversationMemory = Core.append( - accumulator="\n== Conversation History", - ) - - #self.post_process = Core.invoke(path=input.post_process) - - self.prompt(question=input.prompt) - self.conversationMemory(user=input.text) - self.conversationMemory(accumulator=self.conversationMemory.accumulator) - self.prompt(context=self.conversationMemory.accumulator) - self.board_caller = BoardCaller(text=self.prompt.prompt, tools=input.tools) - #self.post_process(input.post_process) - #generator = Core.invoke(id="generator", path=input.generator, text=self.prompt.prompt) - - #self.conversationMemory(assistant=self.board_caller.text) - output(text=self.prompt.text) - input(output) - - - - -class ToolCallInput(SchemaObject): - tools: List[Tool] = Field() - prompt: str = Field() - -class ToolCallOutput(SchemaObject): - text: str = Field(title="Assistant", description="Assistant: Assistant's response in the conversation with the user", required=True) - -class ToolCallBot(Board[ToolCallInput, ToolCallOutput]): - title = "ToolCallBot" - description = "A template for a chatbot with tool-calling capabilities." - type = "tool-call" - version = "0.0.1" - - def describe(self, input, output): - #self.handle_function_calls = HandleFunctionCall(tools=input.tools) - # self.handle_function_calls should be passed in as a board. - self.chatLoop = ChatBot(prompt=input.prompt, tools=input.tools) - output(self.chatLoop) - -class TrivialTool(Board): - title = "Trivial tool" - description = 'Does nothing, for testing purposes' - version = "0.0.1" - - type = "trivial_tool" - - def describe(self, input, output): - output(input) - -import requests - -@breadboard_node -def ping_server(backend_url: str) -> int: - try: - response = requests.get(backend_url, timeout=1) - return response.status_code - except requests.ConnectionError: - return 503 - -class InputSchema(SchemaObject): - backend_url: str = Field(description="Which backend url to send orders to") - -class OutputSchema(SchemaObject): - text: str = Field(title="Assistant", description="Assistant: Assistant's response in the conversation with the user", required=True) - -class CoffeeBot(Board[InputSchema, OutputSchema]): - title = "CoffeBeBot (Python)" - description = 'A recreation of Coffeebot, which is a chatbot that takes in coffee orders and then sends them to a backend.' - version = "0.0.2" - - type = "coffeebot" - - def describe(self, input, output): - tools: List[Tool] = [ - ping_server(backend_url=input.backend_url) - ] - prompt = """HI.""" - self.tool_calling_loop = ToolCallBot(tools=tools, prompt=prompt, backend_url=input.backend_url) - output(self.tool_calling_loop) - -if __name__ == "__main__": - import sys - a = CoffeeBot() - with open(sys.argv[1], "w") as f: - json.dump(a, f, indent=2) \ No newline at end of file diff --git a/packages/breadboard-python/breadboard_python/src/context.py b/packages/breadboard-python/breadboard_python/src/context.py deleted file mode 100644 index c3811c97bf9..00000000000 --- a/packages/breadboard-python/breadboard_python/src/context.py +++ /dev/null @@ -1,20 +0,0 @@ -DESCRIBE_CONTEXT_COUNT = 0 - -class BreadboardDescribeContext(): - def __init__(self): - pass - - def __enter__(self): - global DESCRIBE_CONTEXT_COUNT - DESCRIBE_CONTEXT_COUNT += 1 - print(f"KEX: context count: {DESCRIBE_CONTEXT_COUNT}") - return self - - def __exit__(self, exc_type, exc_value, exc_traceback): - global DESCRIBE_CONTEXT_COUNT - DESCRIBE_CONTEXT_COUNT -= 1 - print(f"KEX: context count after -: {DESCRIBE_CONTEXT_COUNT}") - -def in_breadboard_describe_context(): - global DESCRIBE_CONTEXT_COUNT - return DESCRIBE_CONTEXT_COUNT > 0 \ No newline at end of file diff --git a/packages/breadboard-python/breadboard_python/src/convert_ipnyb.py b/packages/breadboard-python/breadboard_python/src/convert_ipnyb.py deleted file mode 100644 index d91a46ada8d..00000000000 --- a/packages/breadboard-python/breadboard_python/src/convert_ipnyb.py +++ /dev/null @@ -1,55 +0,0 @@ -import sys -import json -from breadboard_python.main import Board, Field, SchemaObject -from breadboard_python.import_node import require -from breadboard_python.adhoc import breadboard_node -import json -from typing import Optional, Union, Callable, List - - -def create_python_board(code: str): - class RunPythonBoard(Board): - title = "Run Python" - type = "runPython" - description = "Runs python code." - _is_node = True - _source_code = code - _pickled_code = None - #_python_version = '.'.join(str(x) for x in sys.version_info[:3]) - _python_version = "3" - def describe(self, input, output): - pass - - def get_configuration(self): - config = super().get_configuration() - if "code" in config: - raise Exception("Code is already populated.") - config["code"] = self._source_code - config["pickle"] = self._pickled_code - config["python_version"] = self._python_version - return config - - return RunPythonBoard - -filename = "packages/breadboard-python/src/breadboard_python/testing-api.ipnyb" -with open(filename, 'r') as f: - notebook = json.load(f) - -nodes = [] -for cell in notebook["cells"]: - source = "".join(cell["source"]) - nodes.append(create_python_board(source)) - -class TestPythonBoard(Board): - title = "Test Python Board on runtime" - description = "Some simple board that's written in Python and runs on an IPython runtime." - def describe(self, input, output): - prev = input - for node in nodes: - prev = node(prev) - output(prev) - -if __name__ == "__main__": - a = TestPythonBoard() - with open(sys.argv[1], "w") as f: - json.dump(a, f, indent=2) \ No newline at end of file diff --git a/packages/breadboard-python/breadboard_python/src/echo.py b/packages/breadboard-python/breadboard_python/src/echo.py deleted file mode 100644 index 6a88ecb5fff..00000000000 --- a/packages/breadboard-python/breadboard_python/src/echo.py +++ /dev/null @@ -1,25 +0,0 @@ - -from main import Board, Field, SchemaObject, List, AttrDict -import json -from typing import Optional, Union - - - -class InputSchema(SchemaObject): - text: str = Field(title="Echo", description="What shall I say back to you?", examples=[], required=True) - -class OutputSchema(SchemaObject): - text: str = Field(title="Answer", description="The answer to the math problem") - -class Echo(Board[InputSchema, OutputSchema]): - title = "Echo" - description = "Echo cho cho cho ho o" - version = "0.0.2" - - def describe(self, input): - self.output = AttrDict() - self.output.text = input.text - return self.output - -a = Echo() -print(json.dumps(a, indent=2)) \ No newline at end of file diff --git a/packages/breadboard-python/breadboard_python/src/import_node.py b/packages/breadboard-python/breadboard_python/src/import_node.py deleted file mode 100644 index f882f9ef5be..00000000000 --- a/packages/breadboard-python/breadboard_python/src/import_node.py +++ /dev/null @@ -1,69 +0,0 @@ -from .main import AttrDict, Board, convert_from_json_to_pydantic - -import javascript -import json - -import importlib - -def restart_javascript_module(): - javascript.config.event_loop.stop() - importlib.reload(javascript.events) - importlib.reload(javascript) - -def require(package_name): - try: - kit_package = javascript.require(package_name) - except javascript.errors.JavaScriptError: - # Sometimes, the javascript module's JS subprocess does not load an npm package properly. - # When restarted, it will load correctly. - restart_javascript_module() - kit_package = javascript.require(package_name) - - a = kit_package() - handlers = a.handlers - - output = AttrDict() - for handler_name in handlers: - - input_schema = {} - output_schema = {} - if handlers[handler_name].describe is None: - pass - else: - b = handlers[handler_name].describe() - res = javascript.eval_js('''JSON.stringify(await b)''') - schema = json.loads(res) - input_schema = schema["inputSchema"] - output_schema = schema["outputSchema"] - if handler_name == "invoke": - pass - input_schema, input_field = convert_from_json_to_pydantic("Input" + handler_name, input_schema) - converted_output_schema, output_field = convert_from_json_to_pydantic("Output" + handler_name, output_schema) - - class ImportedClass(Board[input_schema, converted_output_schema]): - type = handler_name - title = f"Auto-imported {handler_name}" - description = f"This board is auto-imported from {package_name}" - version = "0.?" - _is_node = True - # Need to convert SchemaOutput into something that has context. - output = AttrDict(converted_output_schema) - output_schema1 = converted_output_schema - def __init__(self, **kwargs): - super().__init__(**kwargs) - - if hasattr(self.output_schema1, "additionalProperties") and self.output_schema1.additionalProperties: - self.output["*"] = self - def describe(self, input, output): - pass - def get_configuration(self): - config = super().get_configuration() - if "schema" in config: - config.pop("schema") - return config - - _package_name = package_name - - - output[handler_name] = ImportedClass - return output diff --git a/packages/breadboard-python/breadboard_python/src/main.py b/packages/breadboard-python/breadboard_python/src/main.py deleted file mode 100644 index 413df1b4624..00000000000 --- a/packages/breadboard-python/breadboard_python/src/main.py +++ /dev/null @@ -1,742 +0,0 @@ -from pydantic import BaseModel, Field -from pydantic.fields import FieldInfo -from pydantic_core import core_schema -from pydantic.json_schema import GetJsonSchemaHandler, JsonSchemaValue -from pydantic._internal._model_construction import ModelMetaclass -from typing import Any, Self, Tuple, TypeAlias - -from pydantic import BaseModel -from typing import List, TypeVar, Generic, get_args, Optional, Union, Dict, ClassVar -from jsonref import replace_refs - -import inspect -import json_fix - -def update_json_schema(json_schema, handler: GetJsonSchemaHandler): - #json_schema = handler.resolve_ref_schema(json_schema) - if "allOf" in json_schema: - if "required" in json_schema: - json_schema.pop("required") - if json_schema["allOf"] == [{"properties": [], "type": "object"}]: - pass - # TODO: This is hackily replacing allOf with object. Should check if it's an actual SchemaObject. - json_schema.pop("allOf") - json_schema["type"] = "object" - if "required" in json_schema and isinstance(json_schema["required"], list): - # Update requried based on whether required = True or False - required = [] - for k, v in json_schema["properties"].items(): - if v.get("required", False): - required.append(k) - if "required" in v: - v.pop("required") - json_schema.pop("required") - if required: - json_schema["required"] = required - if "properties" in json_schema: - for k, v in json_schema["properties"].items(): - update_json_schema(v, handler) - if "properties" in json_schema and not json_schema["properties"]: - json_schema.pop("properties") - return json_schema - -def update_final_json_schema(json_schema): - if "anyOf" in json_schema: - assert "type" not in json_schema, f"Unexpectedly type and anyOf both are in json_schema: {json_schema}" - types = [x["type"] for x in json_schema["anyOf"]] - json_schema["type"] = types - json_schema.pop("anyOf") - if "properties" in json_schema: - for k, v in json_schema["properties"].items(): - update_final_json_schema(v) - return json_schema - -class SchemaObject(BaseModel): - @classmethod - def __json__(cls): - # Populate the references, remove definitions. - output = cls.model_json_schema() - output = replace_refs(output, lazy_load=False) - output = update_final_json_schema(output) - if "$defs" in output: - output.pop("$defs") - return output - - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: core_schema.JsonSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - if cls == "toolCalls": - pass - if cls == "toolCallsOutput": - pass - # Remove "title" to make schema look like a normal Object. - json_schema.pop("title") - json_schema = update_json_schema(json_schema, handler) - - return json_schema - - - -class ImportedSchemaObject(SchemaObject): - additionalProperties: ClassVar[bool] = False - @classmethod - def __get_pydantic_json_schema__( - cls, core_schema: core_schema.JsonSchema, handler: GetJsonSchemaHandler - ) -> JsonSchemaValue: - json_schema = handler(core_schema) - json_schema = handler.resolve_ref_schema(json_schema) - if cls == "toolCalls": - pass - if cls == "toolCallsOutput": - pass - # Remove "title" to make schema look like a normal Object. - json_schema.pop("title") - - return json_schema - - - -T = TypeVar('T', bound=SchemaObject) -S = TypeVar('S', bound=SchemaObject) - -UNINITIALIZED = None - -from pydantic import create_model - -def _parse_type_str(type: str): - if type == "string": - return str - if type == "boolean": - return bool - if type == "object": - return SchemaObject - -def _parse_type(schema): - if "type" in schema: - type = schema["type"] - elif "properties" in schema: - type = "object" - elif "items" in schema: - type = "array" - else: - type = "any" - - if type == "string": - return str - if type == "object": - raise Exception("Many possibilities for object.") - #return SchemaObject # This can be any type of SchemaObject. - if type == "array": - inner_schema = schema["items"] - inner_type = _parse_type(inner_schema) - return List[inner_type] - if type == "boolean": - return bool - if isinstance(type, list): - types = tuple(_parse_type_str(x) for x in schema["type"]) - return Union[types] - if type == "any": - return Any - return Any - -def convert_from_json_to_pydantic(name, schema) -> Tuple[Union[BaseModel, type], Field]: - if "properties" in schema and "type" in schema and schema["type"] != "object": - raise Exception(f"Expected type to be object. Got {schema['type']} instead.") - - obj = None - if "properties" in schema: - type = "object" - - output = {} - for k, v in schema["properties"].items(): - output[k] = convert_from_json_to_pydantic(k, v) - obj = create_model(name, __base__=ImportedSchemaObject, **output) - if "additionalProperties" in schema: - obj.additionalProperties = schema["additionalProperties"] - elif schema.get("type") == "object": - obj = SchemaObject - args = {} - for k, v in schema.items(): - if k != "type" and k != "properties" and k != "items": - args[k] = v - return (obj if obj else _parse_type(schema), Field(**args)) - -class FieldContext(FieldInfo): - """Wraps FieldInfo and includes the original Board.""" - _context: Optional["Board"] - inner: FieldInfo - def __init__(self, field_info: FieldInfo, context): - self.inner = field_info - self._context = context - - @property - def _attributes_set(self): - return self.inner._attributes_set - - def __eq__(self, other): - if isinstance(other, FieldInfo) and not isinstance(other, FieldContext): - return self.inner == other - if isinstance(other, FieldContext): - return self.inner == other.inner - return super().__eq__(other) - - def __hash__(self): - key = (self.inner.__hash__, self._context.__hash__) - return hash(key) - - def __getattr__(self, item): - if hasattr(self.inner, item): - return getattr(self.inner, item) - if item in self.inner._attributes_set: - return self.inner._attributes_set[item] - if "annotation" in self.inner._attributes_set.keys(): - if isinstance(self.inner._attributes_set['annotation'], ModelMetaclass): - if item in self.inner._attributes_set['annotation'].model_fields.keys(): - return FieldContext(self.inner._attributes_set['annotation'].model_fields[item], self._context) - raise AttributeError(item) - -""" -Contains a blob of things. Some can be initialized, some may not. -Wildcard "*" means everything. -Can be passed in dict (as part of inputs/outputs), Board, Tuple, and ModelMetaclass (representing schema field) -""" -class AttrDict(dict): - _id = None - def __init__(self, *args, **kwargs): - for arg in args: - # TODO: Handle multiple wildcard matches. - kwargs = kwargs | {"*": arg} - for k, v in kwargs.items(): - if isinstance(v, FieldInfo): - # instantiate a new AttrDict - #v = FieldContext(v) - pass - # TODO: Populate the other field info into the AttrDict. - self[k] = v - def __setattr__(self, key, value): - if key == "_id": - return super().__setattr__(key, value) - self[key] = value - - def get_or_assign_id(self, default_name = None, required=False): - if self._id is not None: - return self._id - if required: - raise Exception(f"Id should be assigned but is not: {self}") - if default_name is not None: - self._id = default_name - else: - # TODO: Fix shared incrementer. It should be tracked based on context. - self._id = f"{self.__type}-{__class__.SHARED_INDEX}" - __class__.SHARED_INDEX += 1 - return self._id - - def __contains__(self, item): - if item == "*": - return True - if super().__contains__(item): - return True - if super().__contains__("*") and isinstance(self["*"], dict): - return item in self["*"] - - def __getattr__(self, item): - if item == "_id": - return super().__getattr__(item) - if item not in self: - return UNINITIALIZED - return self[item] - - def __getitem__(self, item): - if not super().__contains__(item): - return super().__getitem__("*")[item] - return super().__getitem__(item) - - def __call__(self, **kwargs): - for k, v in kwargs.items(): - self[k] = v - return self - - def __hash__(self): - return hash(frozenset(self)) - -def resolve_dict(d): - try: - if "*" in d and isinstance(d["*"], dict): - return d | d["*"] - except KeyError: - return d - return d - -def get_field_name(field: FieldInfo, blob): - """Looks for the field in the blob. If not, checks if field already contains it.""" - for k, v in resolve_dict(blob).items(): - if type(v) == tuple and v[0] == field: - return k - if isinstance(v, FieldContext) and v.inner == field: - return k - if v == field: - return k - if isinstance(v, FieldInfo) and "annotation" in v._attributes_set: - if isinstance(v._attributes_set["annotation"], ModelMetaclass): - try: - return get_field_name(field, v._attributes_set["annotation"].model_fields) - except Exception: - pass - # TODO: FOr wildcard matching, just look for name in fieldinfo. - if "name" in field._attributes_set: - return field._attributes_set["name"] - raise Exception(f"Can't find {field}") - -BOARD_NAMES = {} - -# input schema is either a modelmetaclass or dict -SchemaType = Union[SchemaObject, Dict] - -""" -A Board can have inputs and outputs. -When passed as a parameter, it gives outputs. -""" -class Board(Generic[T, S]): - title = "" - description = "" - version = "" - - type = "unknown-board" - - SHARED_INDEX = {} - output = {} - components = {} - input_board: Optional[Self] = None - output_board: Optional[Self] = None - _is_node: bool = False - _package_name = None - - # This is only used within the context of the parent of this Board, if there is one. - # If there is no parent, this identifier is not used. - # If None, it is not explicitly set yet. In this case, it will default to the attribute field name - # it got assigned to. - # Id should be unique for all components in a parent Board. - id: Optional[str] - - def is_leaf(self) -> bool: - return self._is_node - - def _get_schema(self) -> Tuple[SchemaType, SchemaType]: - # Get input/output schema from typing - if type(self).__orig_bases__[0].__origin__ == Generic: - # This means that the Board is still generic and has no input/output schema defined. - input_schema = Any - output_schema = Any - #raise Exception("Board does not have input and output schemas defined.") - else: - input_schema, output_schema = get_args(type(self).__orig_bases__[0]) - - if not isinstance(input_schema, type) and not isinstance(input_schema, SchemaObject): - raise Exception(f"Invalid type for schema input: {type(input_schema)}") - if not isinstance(output_schema, type) and not isinstance(output_schema, SchemaObject): - raise Exception(f"Invalid type for schema output: {type(output_schema)}") - return input_schema, output_schema - - - def __init__(self, *args, **kwargs) -> None: - self.input_schema, self.output_schema = self._get_schema() - self.components = {} - # For the highest level Board, inputs will always just be the input schemas. - # For the second-level Boards, inputs will be replaced with values or other edges. - # Static values should be on init. Calling should be reserved for edges. - self.inputs: Dict[str, Tuple[Optional[Any], List[Union[FieldContext, Dict, Board]]]] = {} - self.input_fields = {} - self.set_inputs: Dict[str, Any] = {"*": []} - self.id = None - self.loaded = False - self._input_board = None - self._output_board = None - - """ - for k, v in kwargs.items(): - if k == "id": - self.id = v - continue - if isinstance(v, FieldInfo) or isinstance(v, Board) or isinstance(v, AttrDict): # If it's not static - if k not in self.set_inputs: - self.set_inputs[k] = [] - self.set_inputs[k].append(v) - else: - self.inputs[k] = v - - if self.input_schema and isinstance(self.input_schema, ModelMetaclass): - for k, v in self.input_schema.model_fields.items(): - if isinstance(v, FieldInfo): - v = FieldContext(v, self) - else: - raise Exception("Unexpected model_field. No FieldInfo") - if k not in self.inputs: - self.inputs[k] = v - # If k is already populated in the input, no need to populate it now. - """ - - self.__call__(*args, **kwargs) - - - self.output = AttrDict() - if self.output_schema and isinstance(self.output_schema, ModelMetaclass): - for k, v in self.output_schema.model_fields.items(): - if isinstance(v, FieldInfo): - # populate name into fieldinfo if it doesn't exist. - #if not hasattr(v, "name"): - if "name" not in v._attributes_set and (not v.json_schema_extra or "name" not in v.json_schema_extra): - v = FieldInfo.merge_field_infos(FieldInfo(name=k), v, name=k) - v = FieldContext(v, self) - else: - raise Exception("Unexpected model_field. No FieldInfo") - self.output[k] = v - #self.output = AttrDict(self.output_schema.model_fields) - - - def __setattr__(self, name, value): - super().__setattr__(name, value) - if hasattr(self, "components") and name in self.components: - self.components.pop(name) - if isinstance(value, Board) and name not in ["_input_board", "_output_board"]: - self.components[name] = value - - super().__setattr__("loaded", False) - - def __delattr__(self, name: str) -> None: - super().__delattr__(name) - if name in self.components: - self.components.pop(name) - - self.loaded = False - - def __getattr__(self, name): - if name in self.output: - v = self.output[name] - elif "*" in self.output: # when this Board outputs wildcard. - v = FieldContext(FieldInfo(name=name), self) - else: - raise AttributeError(f"Unable to find attribute `{name}` in {self}") - if isinstance(v, FieldInfo) and not isinstance(v, FieldContext): - return FieldContext(v, self) - return v - - def finalize(self): - raise Exception("Not implemented yet") - - def get_configuration(self): - # Filter out anything that's not a reference to another Board, field, or AttrDict. - # get resolved inputs - config = {k: v for k, v in self._get_resolved_inputs().items() if not isinstance(v, FieldContext) and not isinstance(v, Board) and not isinstance(v, dict)} - if self.input_schema and isinstance(self.input_schema, ModelMetaclass): - if "schema" in config: - raise Exception(f"Already have 'schema' key populated in config. This is a reserved field name. Config: {config}") - config["schema"] = self.input_schema.__json__() - for k, v in config.items(): - if inspect.isclass(v): - if issubclass(v, Board): - v = v() - blob = v.__json__() - config[k] = {"board": blob, "kind": "board"} - return config - - def get_or_assign_id(self, default_name = None, required=False): - # TODO: make a unique name registry. - if self.id is not None: - return self.id - if required: - raise Exception(f"Id should be assigned but is not: {self}") - base_name = self.type if default_name is None else default_name - if True: - # TODO: Fix shared incrementer. It should be tracked based on context. - if base_name not in __class__.SHARED_INDEX: - __class__.SHARED_INDEX[base_name] = 1 - self.id = f"{base_name}-{__class__.SHARED_INDEX[base_name]}" - __class__.SHARED_INDEX[base_name] += 1 - return self.id - - def get_or_create_input_output_nodes(self, is_root: bool = False) -> Tuple[Self, Self]: - if self._input_board is not None: - return self._input_board, self._output_board - - # Populate input node. - class InputBoard(Board[self.input_schema, self.input_schema]): - type = "input" if is_root else "passthrough" - _is_node = True - - self._input_board = InputBoard() - assigned_id = "input" if is_root else f"input-{self.get_or_assign_id()}" - self._input_board.get_or_assign_id(assigned_id) - class OutputBoard(Board[self.output_schema, Any]): - type = "output" if is_root else "passthrough" - _is_node = True - - self._output_board = OutputBoard() - assigned_id = "output" if is_root else f"output-{self.get_or_assign_id()}" - self._output_board.get_or_assign_id(assigned_id) - - return self._input_board, self._output_board - - def get_all_components(self) -> List[Self]: - # This can only be ran after describe is called. - all_nodes = [] - - _input_board, output_board = self.get_or_create_input_output_nodes() - all_components = [(k, v) for k, v in self.components.items()] + [(output_board.get_or_assign_id(required=True), output_board)] - - # Component can be a Board or an AttrDict. - already_visited_nodes = set() - def iterate_component(name, component, assign_name=True) -> List[Dict]: - nodes = [] - if component == self: - raise Exception("why") - if isinstance(component, Board): - if component in already_visited_nodes: - return nodes - already_visited_nodes.add(component) - inputs = component.set_inputs - component.get_or_assign_id(name) if name != "*" and assign_name else component.get_or_assign_id(), - nodes.append(component) - - elif isinstance(component, AttrDict): - inputs = component - elif isinstance(component, FieldContext): - nodes.extend(iterate_component(component._context.id, component._context)) - return nodes - else: - raise Exception("Unexpected component type.") - for k, vs in inputs.items(): - for v in vs: - if isinstance(v, Board): - nodes.extend(iterate_component(k, v, assign_name=False)) - elif isinstance(v, AttrDict): - nodes.extend(iterate_component(k, v, assign_name=False)) - elif isinstance(v, FieldContext): - nodes.extend(iterate_component(k, v._context, assign_name=False)) - return nodes - - for name, component in all_components: - all_nodes.extend(iterate_component(name, component)) - - return all_nodes - - def __json__(self): - output = {} - if self.title is not None: - output["title"] = self.title - if self.description is not None: - output["description"] = self.description - if self.version is not None: - output["version"] = self.version - # TODO: Find out what graphs are. - output["graphs"] = {} - output["nodes"] = [] - - # When constructing the graph, two adhoc Boards are added, representing input and output. - input_board, output_board = self.get_or_create_input_output_nodes(is_root=True) - self.describe(input_board, output_board) - - kits = set() - replace_mapping = {} - - - - def expand_boards(parent): - current_nodes = parent.get_all_components() - initial_all_nodes = [x for x in current_nodes] - #current_nodes = set(current_nodes) - result = [] - - for each_component in initial_all_nodes: - # for each component, if they can be expanded, get their input/output nodes. - if each_component.is_leaf(): - if each_component not in result: - result.append(each_component) - continue - i_node, o_node = each_component.get_or_create_input_output_nodes() - each_component.describe(i_node, o_node) - for x in expand_boards(each_component): - if x not in result: - result.append(x) - replace_mapping[each_component] = o_node - - # These inputs need to be added after all boards are expanded. Otherwise board expansion will leak out of the context. - # are these inputs needed when describing? - # probably not? I don't think inputs should override. - for k, vs in each_component.set_inputs.items(): - if not k in i_node.set_inputs: - i_node.set_inputs[k] = [] - i_node.set_inputs[k].extend(vs) - #i_node.set_inputs.update(each_component.set_inputs) - i_node.inputs.update(each_component.inputs) - return result - - all_nodes = expand_boards(self) - - if self.is_leaf(): - self.get_or_assign_id("some-leaf") - all_nodes = [self] - - # Generate nodes - for component in all_nodes: - inputs = component.set_inputs - node = { - # Assign type if is dependency. Assign name if is the Board. - "id": component.get_or_assign_id(required=True), - "type": component.type, - "configuration": component.get_configuration(), - } - output["nodes"].append(node) - - # check for kit - package_name = getattr(component, "_package_name", None) - if package_name: - kits.add(package_name) - - - - """ - class InputBoard(Board[each_component.input_schema, each_component.input_schema]): - type = "input" - - input_component = InputBoard() - input_component.get_or_assign_id(f"{each_component.get_or_assign_id(required=True)}-input") - class OutputBoard(Board[each_component.output_schema, each_component.output_schema]): - type = "output" - - output_component = OutputBoard() - output_component.get_or_assign_id(f"{each_component.get_or_assign_id(required=True)}-output") - each_component.describe(input_component, output_component) - all_nodes.update([input_component, output_component] + each_component.get_all_components()) - replace_mapping[each_component] = output_component - if each_component in all_nodes: - all_nodes.remove(each_component) - """ - - # Populate Edges - output["edges"] = [] - - all_edges = [] - for n in all_nodes: - inputs = n.set_inputs - for k, vs in inputs.items(): - for v in vs: - if v in replace_mapping: - v = replace_mapping[v] - if isinstance(v, Board): - edge = { - "from": v.get_or_assign_id(required=True), - "to": n.get_or_assign_id(required=True), - "out": k, - "in": "" if k == "*" else k, - } - all_edges.append(edge) - elif isinstance(v, FieldContext): - edge = { - "from": v._context.get_or_assign_id(required=True), - # TODO: This is a hacky way to determine node id. AttrDict should be assigned the id. - "to": n.get_or_assign_id(required=True), - "out": get_field_name(v, v._context.output), - "in": k, - } - all_edges.append(edge) - elif isinstance(v, AttrDict): - # When does an AttrDict happen? It's a nested thing... but sometimes it should be done - edge = { - "from": v.get_or_assign_id(required=True), - # TODO: This is a hacky way to determine node id. AttrDict should be assigned the id. - "to": n.get_or_assign_id(required=True), - "out": k, - "in": "" if k == "*" else k, - } - all_edges.append(edge) - else: - raise Exception("Unexpected type") - - output["edges"] = all_edges - - # Populate Kits - output["kits"] = [{"url": f"npm:{x}"} for x in kits] - return output - - def _get_resolved_inputs(self): - resolved_inputs = {} - for k, v in self.inputs.items(): - if k != "*": - resolved_inputs[k] = v - elif isinstance(v, Board): - resolved_inputs[k] = v - else: - resolved_inputs = resolved_inputs | v - return resolved_inputs - - def __call__(self, *args, **kwargs) -> S: - # TODO: For every input passed in, it's possible to have multiple sources of it. - # For instance, a Board can be initialized with a certain value for field1, then get it updated by another Board. - # In this case, we need to store every source of the value. - # One question is: why do I need to call describe here? - # Is it just to have the inputs percolate through? But we have no idea if it is used or not, unless it's defined in Python. - # We should just connect the edges right here. - # There should only be one static input per input field. That ends being in the config., - # There can be many other types of inputs - - # we can take in: Board, dict, or Schema. A Board has a Schema, that is populated - - for k, v in kwargs.items(): - if k in self.inputs and not isinstance(v, FieldContext): - raise Exception(f"Already got an input field: {k}") - - """ - for k, v in kwargs.items(): - if k not in self.set_inputs: - self.set_inputs[k] = [] - self.set_inputs[k].append(v) - """ - for k, v in kwargs.items(): - if k == "id": - self.id = v - continue - if isinstance(v, FieldInfo) or isinstance(v, Board) or isinstance(v, AttrDict): # If it's not static - if k not in self.set_inputs: - self.set_inputs[k] = [] - self.set_inputs[k].append(v) - else: - self.inputs[k] = v - - if self.input_schema and isinstance(self.input_schema, ModelMetaclass): - for k, v in self.input_schema.model_fields.items(): - if isinstance(v, FieldInfo): - v = FieldContext(v, self) - else: - raise Exception("Unexpected model_field. No FieldInfo") - if k not in self.inputs: - self.inputs[k] = v - # If k is already populated in the input, no need to populate it now. - # Arg should be treated as dicts - # TODO: When passed in a whole arg, it should be wildcarded. - - # TODO: Support multiple wildcard edges. - for arg in args: - if isinstance(arg, dict): - self.set_inputs["*"].append(arg) - elif isinstance(arg, SchemaObject): - self.set_inputs["*"].append(arg.model_fields) - elif isinstance(arg, Board): - self.set_inputs["*"].append(arg) - else: - raise Exception(f"Unexpected type for arg: {arg}") - - self.loaded = False - return self - - @staticmethod - def load(data: str) -> S: - pass - def describe(self, input: T, output: S) -> S: - pass - - - - diff --git a/packages/breadboard-python/breadboard_python/src/math.py b/packages/breadboard-python/breadboard_python/src/math.py deleted file mode 100644 index c7fc3cbc378..00000000000 --- a/packages/breadboard-python/breadboard_python/src/math.py +++ /dev/null @@ -1,50 +0,0 @@ -from breadboard_python.main import Board, Field, SchemaObject, List, AttrDict -import json -from typing import Optional, Union - -from breadboard_python.import_node import require -Core = require("@google-labs/core-kit") -Templates = require("@google-labs/template-kit") - - -class InputSchema(SchemaObject): - question: str = Field(title="Math problem", description="Ask a math question", examples=["What is the square root of pi?"], required=True) - generator: str = Field("/graphs/text-generator.json", title="Generator", description="The URL of the generator to call") - -class OutputSchema(SchemaObject): - result: str = Field(title="Answer", description="The answer to the math problem") - -class Math(Board[InputSchema, OutputSchema]): - title = "The Calculator Recipe" - description = "A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems." - version = "0.0.2" - - def describe(self, input): - self.template = Templates.promptTemplate( - id="math-function", - question=input.question, - template="""Translate the math problem below into a self-contained, -zero-argument JavaScript function named \`compute\` that can be executed -to provide the answer to the problem. - -Do not use any dependencies or libraries. - -Math Problem: {{question}} - -Solution:""", - ) - self.generator = Core.invoke( - id="generator", - path=input.generator, - text=self.template.prompt - ) - - self.compute = Core.runJavascript( - name="compute", - code=self.generator.text, - ) - self.output = AttrDict(**{"*": self.compute}) - return self.output - -a = Math() -print(json.dumps(a, indent=2)) \ No newline at end of file diff --git a/packages/breadboard-python/breadboard_python/src/trivial-tool.py b/packages/breadboard-python/breadboard_python/src/trivial-tool.py deleted file mode 100644 index 55db98159fe..00000000000 --- a/packages/breadboard-python/breadboard_python/src/trivial-tool.py +++ /dev/null @@ -1,32 +0,0 @@ - -from breadboard_python.main import Board, Field, SchemaObject -from breadboard_python.import_node import require -import json -from typing import Optional, Union, Callable, List - -Core = require("@google-labs/core-kit") -Templates = require("@google-labs/template-kit") - - - -class InputSchema(SchemaObject): - pass - -class OutputSchema(SchemaObject): - pass - -class TrivialTool(Board[InputSchema, OutputSchema]): - title = "Trivial tool" - description = 'Does nothing, but it shoudl be called to test integration.' - version = "0.0.2" - - type = "trivial_tool" - - def describe(self, input, output): - output(input) - -if __name__ == "__main__": - import sys - a = TrivialTool() - with open(sys.argv[1], "w") as f: - json.dump(a, f, indent=2) \ No newline at end of file diff --git a/packages/breadboard/.eslintrc b/packages/breadboard/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/breadboard/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/breadboard/.npmrc b/packages/breadboard/.npmrc deleted file mode 100644 index 4a1a0c5c72d..00000000000 --- a/packages/breadboard/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -# Ensure npm install fails if the current noder version doesn't match the required version -engine-strict=true diff --git a/packages/breadboard/CHANGELOG.md b/packages/breadboard/CHANGELOG.md deleted file mode 100644 index d26a206ae83..00000000000 --- a/packages/breadboard/CHANGELOG.md +++ /dev/null @@ -1,528 +0,0 @@ -# Changelog - -## 0.27.0 - -### Minor Changes - -- cb8c99a: Feed static describer results to dynamic describer. -- 4dadf16: Introduce experimental storeData and retrieveData components in Core Kit. -- 8f9fddf: Move LightObserver to shared-ui as TopGraphObserver. -- f61ccf3: Introduce URL-based component types. -- 8540b93: Convert Content to Build API and merge Specialist 2 to Specialist. -- 81eafad: Implement selecting runs and viewing them. -- 4c03455: Introduce Specialist 2 and make Content component support LLM Content. -- 157c31e: Implement remote board server -- d7606d3: Implement plumbing for visualizing runs as graphs. -- d9fd0ab: [project-store] -> [idb-board-server] -- a6128a3: Switch Visual Editor to use Run API. - -### Patch Changes - -- 703f17d: Various fixes to make board server work again. -- 6136d87: Bug fixes for dynamic describers. -- e61fa66: Dispatch "edge" event for all edges. -- a104fa7: Teach InspectableRunObserver.load to add the loaded run to its runs. -- 8a1b8c4: Teach Throttler to not wait on new data if it already has cached data. -- 9797718: Auto-migrate IDB `GraphProvider` boards -- 3137076: Include credentials in proxy client fetch. -- 4cc71ee: Allow pasting star edges. -- a039d2e: Do a little tidy up of the UI -- 9783ba8: Fix worker memory leak and throttle describers. -- aafec7f: Correctly account for the default start tags. -- 1ad3001: Show configuration previews underneath ports -- 84ca649: Introduce the "Content" component. -- Updated dependencies [8d06f3c] -- Updated dependencies [8540b93] - - @google-labs/breadboard-schema@1.8.0 - -## 0.26.0 - -### Minor Changes - -- 7d46a63: Teach Visual Editor to use board server's node proxy to run boards. - -## 0.25.0 - -### Minor Changes - -- e0dccfe: Polish app view. -- 6404cb3: Introduce HarnessRunner API (not yet exposed). -- 9ad0524: Teach Inspector API about start tags. -- a4301e6: Introduce the ability to write custom describers. -- 7fdd660: Add the Run API. -- a34bb69: Introduce RemoteRunner (over HTTPS) -- c397d53: Add support for multiple graph entry points and start tags. -- 7de241c: Remove `BoardRunner`. -- a424c92: Teach remote runner to send fewer bytes over the wire. -- 79d709c: Introduce Edge event to Local and Remote runners. - -### Patch Changes - -- 49b3612: Restore preview functionality -- b201e07: Implement edge-based UI in board-server (and fix a bunch of bugs elsewhere) -- 15b5659: Teach app view to use RemoteRunner. -- 0296c89: Teach LLMContentArray check to ignore $metadata -- 534d67e: Teach Run Store & Data Store about LLM Content Array -- c2cd40d: Add InspectableRunEdgeEvent -- 262cefd: Skip metadata events in DataStore and RunStore -- Updated dependencies [c397d53] - - @google-labs/breadboard-schema@1.7.0 - -## 0.24.0 - -### Minor Changes - -- 8c694ed: Support sequences of nested graphs (like what `reduce` does). -- bbf2c30: Plumb interruptible run to board server. -- 14df6a8: Retry with credentials when board fetch fails. -- 2aabb7a: Introduce the concept of `partialOutputs` to `TraversalState`, to convey outputs produced while processing bubbled inputs. -- fb72771: Introduce run reanimation and `interruptibleRunGraph`. -- 9b22cab: Make sure that reanimator correctly adjusts invocationId when resuming. -- 00cc2c5: Remove `lambda`, introduce standalone `invokeGraph` and `runGraph` functions, and other plumbing refactoring. -- c04cff0: Bring back synchronous `TraversalResult.outputs`. -- 3f8cdd1: Introduce run store -- 3a5ced1: Refactor `map` to run serially when `RunStateManager` is present. - -### Patch Changes - -- 1dc645a: Remove `validator` and `slot` bits from BoardRunner and allow bubbled inputs to abort gracefully. -- 62f8d5b: Fix replay of saved runs - -## 0.23.0 - -### Minor Changes - -- 1e1be2a: Teach board-server run API endpoint to run simple boards. -- 2b9ef5b: Rewrire Datastore usage -- 2312443: Add support for `deprecated` and `experimental` tags on Kits. -- 6ffa89c: Migrate to new data-store package - -### Patch Changes - -- 2b094a3: Add google-drive-query behavior -- fa93c3f: Add drop function to datastore -- 215bd15: Add google-drive-file-id -- a0852df: Update titles and help links in Core Kit. -- Updated dependencies [2312443] - - @google-labs/breadboard-schema@1.6.0 - -## 0.22.0 - -### Minor Changes - -- ffbf163: canConnect now checks JSON schema compatibility in a much more complete way, including understanding of nested types. - -### Patch Changes - -- a925cf0: Add inPort and outPort functions to InspectableEdge -- 5cf08f1: Add "wires" property to NodeDescriberContext which exposes a describe() function for getting the actual schema of a connected port if needed. -- 8928fb7: Add section for Visual Editor documentation -- d6706f2: Add analyzeCanConnect method to InspectablePort which is like canConnect but with detailed error messages. -- 5447426: Add kind port to InspectablePort to tell you whether it's an input or output port -- 7e1f01c: Start rolling up .d.ts type information for the package. -- Updated dependencies [dd783e0] -- Updated dependencies [3aba1a4] - - @google-labs/breadboard-schema@1.5.1 - -## 0.21.0 - -### Minor Changes - -- 74ade20: Confine the number of inspectable runs to two. -- 59dd0f5: Add support for "mine" property -- 417323c: Teach Board Server to use Node Proxy Server -- b3aa884: Introduce undo/redo capability in Editor API. -- 7af14cf: Add support for comment nodes -- 778f7aa: Teach Breadboard to load runs with non-text content. -- 808f5e2: Introduce graph edit history API. -- e0fdbc3: Use LLMContent types in blank graphs. -- 14853d5: Add Gemini Nano node. -- 8798514: Combine several Editor API methods to one `edit`. -- eb64b9a: Export enum values -- 91cb723: Teach Editor API to properly roll back multiple graph changes. -- 3e10f0f: Introduce `DataCapability` and add support for multipart form data in `fetch`. -- c53ca01: Plumb `DataStore` throuh to `NodeHandlerContext`. -- 9491266: Implement `DataStore` and a simple implementation. -- 2ace620: Teach `InspectableGraph.describe` to correctly propagate fixed/flexible bit. -- 37418d9: Introduce the `iframe.html` entry point for running Breadboard in an iframe. -- 083f69c: Add validate() method to InspectableEdge -- 5b03d96: Start using multi-edit capability when pasting nodes. -- f0d8d67: Remove the old "star port as ad-hoc port drop zone" machinery. -- 836389d: Implement `InspectableRun.replay` for past runs. -- 225c7cc: Implement simple ACL for board server. - -### Patch Changes - -- 5a55b7d: Don't prefill inputs from bubbled inputs. -- 3d7b4a7: Introduce optional `help` metadata for graphs and kits. -- fea8967: Add basic "Save As..." support -- 54b03b9: Update nav styling -- 810d7fd: Fix canGoBack check -- 32a48a3: Teach `output` to be non-fixed by default. -- cd73b17: Switch to Nodejs v20.14.0 as the baseline. -- 81d82fe: Don't update events when looking up event data. -- 2a7531b: Actually initialize `InspectablePort.type`. -- 7c1b4cb: Temporarily mark new board server boards as published. -- 702cfe1: Unblock UI on Providers -- bebd96e: Move a bunch of docs over to archive. -- 4c681cb: Switch to use edit operations machinery in Editor API internals. -- fb2e584: Make metadata/configration changes incremental by default. -- fcef799: Update `help` to have description and URL -- Updated dependencies [3d7b4a7] -- Updated dependencies [7af14cf] -- Updated dependencies [511bd9b] -- Updated dependencies [431fa3d] -- Updated dependencies [cd73b17] -- Updated dependencies [fcef799] - - @google-labs/breadboard-schema@1.5.0 - -## 0.20.0 - -### Minor Changes - -- 8097177: Allow output ports to be required in their schema without it turning output ports red when they are unwired -- cec6d54: Introduce `InspectablePortType`. -- 3397974: Add `InspectableNode.type()` and start using it. - -### Patch Changes - -- ab9a4ce: Remove `runRemote` method. It is old code that doesn't work and isn't used. -- a35406c: Add formatGraphDescriptor function which formats BGL in a deterministic way -- 477e6e6: Sort more schema fields for easier comparison across serializers - -## 0.19.0 - -### Minor Changes - -- 63eb779: Add support for `interactiveSecrets` option on `RunConfig`. - -## 0.18.0 - -### Minor Changes - -- cef20ca: Enable running edgeless graphs -- 54baba8: Implement `AbortSignal` support. -- cdc23bb: Make bubbled input values configurable. -- a1fcaea: Introduce `code` behavior hint. -- c3ed6a7: Introduce `InspectableRun.inputs`. -- 3d48482: Change all multi-modal inputs to be a format of llm-content -- 626139b: Support `icon` metadata on node types and graphs. -- bd44e29: Support audio input -- 43da00a: Introduce the concept of editor modes. -- c3587e1: Introduce `GraphDescriptor.metadata`. - -### Patch Changes - -- fbf7a83: Apply `format` to array items. -- 49c3aa1: Make `inputs` and `descriptor` optional for ErrorObject. -- 416aed2: Introduce `metadata` for `NodeHandler` entries, teaching node types in Kits to describe themselves. -- f2eda0b: Fix lots of bugs around Tool Worker. -- 3f9507d: Better compatibility with @breadboard-ai/build -- Updated dependencies [416aed2] - - @google-labs/breadboard-schema@1.4.1 - -## 0.17.0 - -### Minor Changes - -- ae79e4a: Implement `InspectableRun.currentNodeEvent`. -- 72c5c6b: Split run-time and build-time URL resolutions for loading graphs. -- c5ba396: Introduce `InspectableRun.stack` method. -- 51159c4: Introduce `InspectableEdge.type`. -- 6f9ba52: Add support for control edges. - -### Patch Changes - -- c3cb25f: Make star edge fix up work in reverse, too. -- dd810dd: Introduce `GraphChangeEvent.visualOnly` to indicate that only visual metadata was updated. -- 7bafa40: Introduce `graphchangereject` event in Editor API. -- 2932f4b: Remove `schema` from `output` ports. - -## 0.16.0 - -### Minor Changes - -- ad9c233: Allow adding edges between `star` and named ports. -- 65d869b: Teach Editor API about versions and change events. -- cf0ee4f: Add `blank` method to Editor API. -- 5382365: Add `InspectableGraph.graphs` API. -- ffd2a6c: Implement subgraph editing in Editor API. - -### Patch Changes - -- 417cdf5: Switch to use `GraphDescriptors` in subgraph editing. -- 43cbed7: Remove `messages` and `currentNode` from `InspectableRun`. -- ff6433c: Prepare InspectableGraph instances to have a mutable backing store. -- 0e7f106: Add `metadata` to `InspectableNode`. -- 9ea6ba0: A quick-and-dirty fix to the TS type system errors. - -## 0.15.0 - -### Minor Changes - -- 938015d: Use `runJavascript` directly in `code` block. - -### Patch Changes - -- 76da09d: Early support for voting (yes/no) in Human node. - -## 0.14.0 - -### Minor Changes - -- e8d0737: Make run serialization more compact. - -## 0.13.0 - -### Minor Changes - -- 51a38c0: Teach `InspectableRunNodeEvent` to use `InspectableNode` by default. -- 9326bd7: Introduce ability to save/load runs. - -### Patch Changes - -- faf1e12: Teach invoke to be more accepting of uncertainty. -- d49b80e: Introduce `InspectableRun.getEventById` method. -- fbad949: Various schema-related bug fixes. - -## 0.12.1 - -### Patch Changes - -- 2fda461: Add missing build artifacts - -## 0.12.0 - -### Minor Changes - -- 866fc36: Refactor `BoardLoader` to be a `GraphLoader` implementation. -- f005b3b: Introduce `load` API for kits. -- 048e8ec: Introduce `InspectableRunEvent` and API around it. -- 60bd63c: Get the Run Inspector API ready to ship -- 04d5420: Adds describer to GraphToKitAdapter -- 1b48826: Introduce `GraphProvider` and make it pluggable. -- 3e8cfcf: Teach `InspectableRunNodeEvent` about `InspectableNode`. -- 986af39: Update GraphProvider to support additional methods; land IDBGraphProvider -- eabd97b: Introduce the concept of log levels in Run Inspector API. -- 2008f69: Teach breadboard to load custom URL types. -- a8fc3f3: Teach `GraphProvider` to watch for file change notifications. -- c208cfc: Introduce `canChangeEdge` and `changEdge` to the Editor API. - -### Patch Changes - -- 99446b8: Various quality improvements to schemas and Graph Inspector API. -- a8bab08: Add support for inputs (including bubbled) to `InspectableRun.events`. -- decfa29: Introduce `DebuggerGraphProvider`. -- dcfdc37: Implement handling subgraphs in Run Inspector API. -- d971aad: Add documentation for Run Inspector API. -- dc35601: Improved run inspector API to mostly work. -- 9cda2ff: Disallow creation of non-star to star edges. -- 764ccda: Use behaviors to identify port editing UI. -- 56b90a4: Improve graph unique id generation and various cleanups. -- e648f64: Start using UUIDs for graphs. -- ad5c1be: Introduce Tool Worker node in Agent Kit. -- 4a4a1f6: Place unfinished sidecar events at the bottom of the event list. -- bac9bb1: Bring loader machinery closer to cacheable load state. -- 3c497b0: Use esbuild.build to compile the boards. This enables importing modules. -- c0f785a: Shift more URL-resolution logic into the Loader. -- 32cfbaf: Optimistically create edge instances during cache miss. -- 8dc4e00: Fix a race condition in Worker transport. -- 6438930: Make `InspectableEdge` and `InspectableNode` instances stable. -- dd2cce6: Make graph editor work with stable `InspectableEdge`. -- cac4f4f: Add `InspectableRunEvent.id`. -- b1fc53b: Teach `breadboard debug` to load PaLM Kit dynamically. -- ef05634: Allow node describe() and invoke() to work as long as an object provides those properties -- Updated dependencies [f005b3b] -- Updated dependencies [9b8e732] -- Updated dependencies [4a4a1f6] -- Updated dependencies [eabd97b] -- Updated dependencies [efeb1a3] - - @google-labs/breadboard-schema@1.4.0 - -## 0.11.2 - -### Patch Changes - -- 07e66bf: Updated README.md - -## 0.11.1 - -### Patch Changes - -- 05136f8: Various fixes to the inspector API. -- ef305d1: Enable adding input/output nodes with the Editor API. -- aea9178: Delete affected edges when removing a node in editor API. -- 20a0e5c: Fix self not defined error - -## 0.11.0 - -### Minor Changes - -- c19513e: Introduce `InspectableGraph.edges()` and start using it. -- 2237a4c: Added `subgraph` method to `InspectableNode`. -- bd68ebd: Add a simple `describe` method to InspectableGraph. -- ea652f3: Introduce the Editor API. -- 0085ee2: Teach inspector API to correctly describe nodes. -- ee00249: Introduce `NodeMetadata`. -- c13513f: Introduce Inspector API (a little baby one) -- c804ccc: Introduce the `InspectablePort.edges` property. -- 53406ad: Zod Schema is no longer supported. JSON Schema should be used instead. -- 4c5b853: Implement output bubbling. -- 3f3f090: Teach `jsonata` and `invoke` nodes to better describe themselves. -- d7a7903: Added support for describing inputs, outputs, and subgraphs in Inspector API. -- f6e9b2c: Teach the Breadboard CLI how to use proxies - -### Patch Changes - -- 9a76a87: Various fixes to Editor API found while playing with the visual editor. -- 56954c1: Introduce `InspectableNode.ports`, which enumerates ports of a node. -- 0ef9ec5: Added documentation for Inspector API. -- 56ccae5: Introduce a way to inspect kits. -- 4920d90: Taught `core.invoke` to describe its own subgraphs. -- 10a8129: Add docs for the Agent Kit -- 5a65297: Add dependency on schema package for new graph types location -- 4401a98: Fix various bugs in inspector API. -- Updated dependencies [ee00249] -- Updated dependencies [5a65297] - - @google-labs/breadboard-schema@1.3.0 - -## 0.10.1 - -### Patch Changes - -- fb1c768: Introduce Gemini Kit. - -## 0.10.0 - -### Minor Changes - -- 9bcd607: Implement `isImage` type annotation. - -### Patch Changes - -- f6a7f43: Add schemas to serialised boards -- Updated dependencies [e7be365] -- Updated dependencies [f6a7f43] - - @google-labs/breadboard-schema@1.2.0 - -## 0.9.1 - -### Patch Changes - -- 81e2840: Teach Breadboard about transient bubbled inputs. - -## 0.9.0 - -### Minor Changes - -- 8eccdad: [breadboard-cli] Improvements to OpenAPI import to handle parameters as dynamic inputs and input config files -- 6e8c08d: remove breadboard json schema - -### Patch Changes - -- 780909c: Stop displaying subgraphs in Breadboard Debugger. -- bba68fd: Write the introduction in the "Happy Path" doc. -- b557794: The "recipe" function is now called "board". A "recipe" alias is still exported to ease migration. -- a9206fc: Firm up the error return type. -- 931a95b: Introduce richer error reporting to the harness. - -## 0.8.0 - -### Minor Changes - -- af00e58: Various changes. First release managed by Changesets. - -## [0.6.0] - 2023-12-06 - -- Bug fixes -- New `remote` submodule to enable invoking boards over HTTP and workers -- The new syntax! (WIP) -- The `ui` submodule moved to its own package `breadboard-ui` -- [Bubbling](https://github.com/breadboard-ai/breadboard/issues/166) inputs! - -## [0.5.1] - 2023-11-18 - -- Removed unintended dependency on `jsonschema`. -- Removed circular dependency between `Board` and `BoardRunner`. -- Other bug fixes. - -## [0.5.0] - 2023-11-08 - -- The `/ui` submodule changes: - - supports multiple simultaneous inputs - - does not ask for keys more than once per session - - if you specify `type: "object"` for an input, it will try to parse it as JSON data and pass as an object. - - draw Mermaid diagrams of the boards - - there's now a link to the running board in the UI. -- The `/worker` submodule changes: - - bug fixes (will actually queue received messages and not drop them on the floor) -- The following nodes moved out into the Core Kit: `passthrough`, `reflect`, `slot`, `include`, `import`, and `invoke`. -- The `run` method now takes a `NodeHandlerContext` object as its argument, rather than a list of arguments. -- Kits are no longer implicitly imported by Breadboard. Instead, supply loaded Kits as part `NodeHandlerContext` to `run`. - -## [0.4.1] - 2023-10-20 - -- Moved the `mermaid` method to `BoardRunner`. -- Updated URL resolution on constructed Kits. -- Tweaked documentation. -- Multiline support and loading from URL in UI elements -- Other fixes. - -## [0.4.0] - 2023-10-17 - -- **M2 Release** -- Added minified build artifacts. -- Three new nodes: `invoke`, `import`, and `lambda` (see [documentation](https://github.com/breadboard-ai/breadboard/blob/13601657112736ccccb083ed3e167f7e2ae05928/packages/breadboard/docs/nodes.md)) -- Deprecated `include` node (the `invoke` node replaces it) -- Rolled `graph-runner` package in. This package now has zero prod dependencies. -- Added a way for nodes to describe themselves in `NodeHandler`. -- All nodes now describe themselves using the mechanism above. -- Added `SchemaBuilder` for easy building of node descriptions. -- Added `/kits` submodule as a future place for easily creating kits -- Added `GenericKit` abstraction for automatically generating kits from handlers. -- Added `/ui` submodule as the future place for simple Web-based UI for Breadboard. -- Added `/worker` submodule as the future place way to build Breadboard-based Web Workers. -- Added the notion of subgraphs (graphs that are embedded into a larger `GraphDescriptor`). -- Edge inputs are now queued (fixes the issue of new outputs overwriting old ones) -- Node outputs are now asynchronous -- Lots of fixes and love and care. - -## [0.3.1] - 2023-09-15 - -- Updated milestone shield. - -## [0.3.0] - 2023-09-15 - -- There is no more `seeksInput` property on `RunResult`. Instead, the `type` property will tell us why the board paused. Currently, three valid results are `input`, `output`, and `beforehandler`. The first two existed before. The third one now interrupts before running every node. -- The boards now can store metadata about them. See https://github.com/breadboard-ai/breadboard/blob/main/packages/graph-playground/graphs/call-react-with-slot.json for an example. Yes, you can put Markdown in description. -- The boards now have URLs associated with them. When a board is loaded from a URL, the `url` property will reflect that value. All subsequent URLs are resolved relative to the URL of the board. -- If the URL is not supplied, the board is assumed to have a URL of the current working directory of whatever loaded the board. -- There's a `ResultRun.isAtExitNode` method that reports true if the currently visited node is an exit node for the graph. -- There's a `Board.runRemote` method that allows running a board remotely (powered by `packages/breadboard-server`). This functionality is nascent and may not work exactly as expected. - -## [0.2.0] - 2023-09-02 - -- New `beforehandler` event -- New `DebugProbe` that is useful for debugging boards -- New `RunResult` class with `load` and `save` methods to support multi-turn and continuous runs. - -## [0.1.1] - 2023-08-23 - -- updated the homepage URL (oops). - -## [0.1.0] - 2023-08-23 - -- lots of tutorial updates -- `run` and `runOnce` now have `slot` parameter to pass in slotted graphs -- `BreadboardRunResult` now has a `node` property that contains current node -- integrity validator plumbing -- bug fixes and refactorings - -## [0.0.2] - 2023-08-04 - -- updated compiled Javascript (oops). - -## [0.0.1] - 2023-08-04 - -- started a changelog -- [M0 release](https://github.com/breadboard-ai/breadboard/issues?q=is%3Aissue+milestone%3A%22Breadboard+M0%22+is%3Aclosed) diff --git a/packages/breadboard/README.md b/packages/breadboard/README.md deleted file mode 100644 index 4a12bba8308..00000000000 --- a/packages/breadboard/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Breadboard Core Library - -To learn more about Breadboard, go to [Breadboard docs site](https://breadboard-ai.github.io/breadboard/). diff --git a/packages/breadboard/package.json b/packages/breadboard/package.json deleted file mode 100644 index 128f288c8d1..00000000000 --- a/packages/breadboard/package.json +++ /dev/null @@ -1,183 +0,0 @@ -{ - "name": "@google-labs/breadboard", - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "version": "0.27.0", - "description": "A library for rapid generative AI application prototyping", - "main": "./dist/src/index.js", - "exports": { - ".": "./dist/src/index.js", - "./kits": "./dist/src/kits/index.js", - "./remote": "./dist/src/remote/index.js", - "./harness": "./dist/src/harness/index.js" - }, - "types": "dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "test": "wireit", - "test:node": "wireit", - "build": "wireit", - "build:tsc": "wireit", - "build:rollup": "wireit", - "lint": "wireit", - "merm": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "build:rollup", - "build:tsc" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "dependencies": [ - "../schema:build" - ], - "env": { - "FORCE_COLOR": "1" - }, - "files": [ - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "tests/bgl/*.bgl.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/", - "!dist/**/*.min.js{,.map}" - ], - "clean": "if-file-deleted" - }, - "build:rollup": { - "command": "rollup -c", - "dependencies": [ - "build:tsc" - ], - "files": [ - "rollup.config.js", - "package.json" - ], - "output": [ - "dist/**/*.min.js{,.map}" - ] - }, - "test": { - "dependencies": [ - "test:ava", - "test:node" - ] - }, - "test:ava": { - "command": "ava", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - "tests/**/*.json", - "!tests/node/**/*.ts" - ], - "output": [] - }, - "test:node": { - "command": "node --test --enable-source-maps --test-reporter spec dist/tests/node/**/*.js", - "dependencies": [ - "build:tsc" - ], - "files": [ - "tests/node/*.ts", - "tests/bgl/*.bgl.json" - ], - "output": [] - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - }, - "merm": { - "command": "node scripts/make-graphs.js", - "dependencies": [ - "build:tsc" - ], - "files": [ - "scripts/make-graphs.js", - "tests/data/**/*.json" - ], - "output": [ - "docs/graphs/**/*.md" - ] - } - }, - "repository": { - "directory": "packages/breadboard", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src", - "dist/*.js", - "dist/*.js.map" - ], - "ava": { - "timeout": "30s", - "files": [ - "tests/**/*.ts", - "!tests/type-checks.ts", - "!tests/node/**/*.ts", - "!tests/inspector/inline-data-*.ts" - ], - "workerThreads": false, - "typescript": { - "rewritePaths": { - "./": "dist/" - }, - "compile": false - } - }, - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/breadboard#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@definitelytyped/dtslint": "^0.2.23", - "@google-labs/tsconfig": "^0.0.1", - "@rollup/plugin-node-resolve": "^15.3.0", - "@rollup/plugin-terser": "^0.4.4", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "jsonschema": "^1.4.1", - "rollup": "^4.22.4", - "rollup-plugin-dts": "^6.1.1", - "@rollup/plugin-json": "^6.1.0", - "typescript": "^5.6.2" - }, - "engines": { - "node": ">=20.14.0" - }, - "dependencies": { - "@google-labs/breadboard-schema": "^1.8.0", - "json-schema": "^0.4.0" - } -} diff --git a/packages/breadboard/rollup.config.js b/packages/breadboard/rollup.config.js deleted file mode 100644 index cbd2bb28d5f..00000000000 --- a/packages/breadboard/rollup.config.js +++ /dev/null @@ -1,31 +0,0 @@ -import json from "@rollup/plugin-json"; -import { nodeResolve } from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import config from "./package.json" with { type: "json" }; -import dts from "rollup-plugin-dts"; - -const makeAllTargets = Object.entries(config.exports).map(([name, input]) => { - name = name === "." ? "index" : name; - const file = `dist/${name}.min.js`; - return { - input, - output: { - file, - format: "esm", - plugins: [terser()], - sourcemap: true, - }, - plugins: [nodeResolve(), json()], - }; -}); - -makeAllTargets.push({ - input: "dist/src/index.d.ts", - output: { - file: "dist/index.d.ts", - format: "esm", - }, - plugins: [dts()], -}); - -export default makeAllTargets; diff --git a/packages/breadboard/scripts/make-graphs.js b/packages/breadboard/scripts/make-graphs.js deleted file mode 100644 index 75a679416e3..00000000000 --- a/packages/breadboard/scripts/make-graphs.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * A script to generate graphs from various JSON files laying around this - * package. - * - * Generates one markdown file per directory. - */ - -import { readFile, writeFile, readdir, mkdir } from "fs/promises"; - -import { toMermaid } from "@google-labs/breadboard"; - -const IN_DIRS = ["tests/data"]; -const OUT_DIR = "./docs/graphs"; - -const ensureDir = async (dir) => { - await mkdir(dir, { recursive: true }); -}; - -const readGraphs = async (dir) => { - const files = (await readdir(`${dir}/`)).filter((file) => - file.endsWith(".json") - ); - const graphs = await Promise.all( - files.map(async (file) => { - const graph = await readFile(`${dir}/${file}`, "utf-8"); - return { - file, - graph: JSON.parse(graph), - }; - }) - ); - return graphs; -}; - -await ensureDir(OUT_DIR); -await Promise.all( - IN_DIRS.map(async (dir) => { - const graphs = await readGraphs(dir); - const mermaid = graphs - .map(({ file, graph }) => { - const mermaid = toMermaid(graph, "LR"); - return `## ${file}\n\n\`\`\`mermaid\n${mermaid}\n\`\`\``; - }) - .join("\n\n"); - const markdown = `# ${dir}\n${mermaid}`; - await writeFile(`${OUT_DIR}/${dir.replace("/", "-")}.md`, markdown); - }) -); diff --git a/packages/breadboard/src/board.ts b/packages/breadboard/src/board.ts deleted file mode 100644 index 1b0628a7920..00000000000 --- a/packages/breadboard/src/board.ts +++ /dev/null @@ -1,188 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - Edge, - NodeDescriptor, - InputValues, - OutputValues, - GraphDescriptor, - SubGraphs, - GraphInlineMetadata, -} from "./types.js"; - -import type { - Breadboard, - Kit, - KitConstructor, - OptionalIdConfiguration, - BreadboardNode, -} from "./types.js"; - -import { Node } from "./node.js"; -import { asComposeTimeKit } from "./kits/ctors.js"; - -import breadboardSchema from "@google-labs/breadboard-schema/breadboard.schema.json" with { type: "json" }; - -/** - * This is the heart of the Breadboard library. - * Just like for hardware makers, the `Board` is the place where wiring of - * a prototype happens. - * - * To start making, create a new breadboard: - * - * ```js - * const board = new Board(); - * ``` - * - * For more information on how to use Breadboard, start with [Chapter 1: Hello, world?](https://github.com/breadboard-ai/breadboard/tree/main/packages/breadboard/docs/tutorial#chapter-7-probes) of the tutorial. - */ -export class Board implements Breadboard, GraphDescriptor { - // GraphDescriptor implementation. - url?: string; - title?: string; - description?: string; - $schema?: string; - version?: string; - edges: Edge[] = []; - nodes: NodeDescriptor[] = []; - graphs?: SubGraphs; - args?: InputValues; - - /** - * - * @param metadata - optional metadata for the board. Use this parameter - * to provide title, description, version, and URL for the board. - */ - constructor( - { url, title, description, version, $schema }: GraphInlineMetadata = { - $schema: breadboardSchema.$id, - } - ) { - Object.assign(this, { - $schema: $schema ?? breadboardSchema.$id, - url, - title, - description, - version, - }); - } - - #closureStack: Board[] = []; - #topClosure: Board | undefined; - #acrossBoardsEdges: { edge: Edge; from: Board; to: Board }[] = []; - - /** - * Core nodes. Breadboard won't function without these. - * These are always included. - */ - - /** - * Places an `input` node on the board. - * - * An `input` node is a node that asks for inputs from the user. - * - * See [`input` node reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/breadboard/docs/nodes.md#input) for more information. - * - * @param config - optional configuration for the node. - * @returns - a `Node` object that represents the placed node. - */ - input( - config: OptionalIdConfiguration = {} - ): BreadboardNode { - const { $id, ...rest } = config; - return new Node(this, undefined, "input", { ...rest }, $id); - } - - /** - * Places an `output` node on the board. - * - * An `output` node is a node that provides outputs to the user. - * - * See [`output` node reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/breadboard/docs/nodes.md#output) for more information. - * - * @param config - optional configuration for the node. - * @returns - a `Node` object that represents the placed node. - */ - output( - config: OptionalIdConfiguration = {} - ): BreadboardNode { - const { $id, ...rest } = config; - return new Node(this, undefined, "output", { ...rest }, $id); - } - - addEdge(edge: Edge) { - this.edges.push(edge); - } - - addNode(node: NodeDescriptor): void { - this.nodes.push(node); - } - - /** - * Adds a new kit to the board. - * - * Kits are collections of nodes that are bundled together for a specific - * purpose. For example, the [Core Kit](https://github.com/breadboard-ai/breadboard/tree/main/packages/core) provides a nodes that - * are useful for making boards. - * - * Typically, kits are distributed as NPM packages. To add a kit to the board, - * simply install it using `npm` or `yarn`, and then add it to the board: - * - * ```js - * import { Board } from "@google-labs/breadboard"; - * import { Core } from "@google-labs/core-kit"; - * - * const board = new Board(); - * const kit = board.addKit(Core); - * ``` - * - * @param ctr - the kit constructor. - * @returns - the kit object, which is associated with - * the board and can be used to place nodes on that board. - */ - addKit(ctr: KitConstructor): T { - const kit = asComposeTimeKit(ctr, this); - return kit as T; - } - - /** - * Used in the context of board.lambda(): Returns the board that is currently - * being constructed, according to the nesting level of board.lambda() calls - * with JS functions. - * - * Only called by Node constructor, when adding nodes. - */ - currentBoardToAddTo(): Breadboard { - const closureStack = this.#topClosure - ? this.#topClosure.#closureStack - : this.#closureStack; - if (closureStack.length === 0) return this; - else return closureStack[closureStack.length - 1]; - } - - /** - * - */ - addEdgeAcrossBoards(edge: Edge, from: Board, to: Board) { - if (edge.out === "*") - throw new Error("Across board wires: * wires not supported"); - - if (!edge.constant) - throw new Error("Across board wires: Must be constant for now"); - - if (to !== this) - throw new Error("Across board wires: Must be invoked on to board"); - - const closureStack = this.#topClosure - ? this.#topClosure.#closureStack - : this.#closureStack; - if (from !== this.#topClosure && !closureStack.includes(from)) - throw new Error("Across board wires: From must be parent of to"); - - this.#acrossBoardsEdges.push({ edge, from, to }); - } -} diff --git a/packages/breadboard/src/bubble.ts b/packages/breadboard/src/bubble.ts deleted file mode 100644 index 5bea9b4a91f..00000000000 --- a/packages/breadboard/src/bubble.ts +++ /dev/null @@ -1,234 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { InputStageResult, OutputStageResult, RunResult } from "./run.js"; -import type { RunState } from "./run/types.js"; -import { loadRunnerState, saveRunnerState } from "./serialization.js"; -import type { - GraphInlineMetadata, - InputValues, - NodeDescriptor, - NodeHandlerContext, - NodeValue, - OutputValues, - RunArguments, - Schema, - TraversalResult, -} from "./types.js"; - -export const createErrorMessage = ( - inputName: string, - metadata: GraphInlineMetadata = {}, - required: boolean -): string => { - const boardTitle = metadata.title ?? metadata?.url; - const requiredText = required ? "required " : ""; - return `Missing ${requiredText}input "${inputName}"${ - boardTitle ? ` for board "${boardTitle}".` : "." - }`; -}; - -export const bubbleUpInputsIfNeeded = async ( - metadata: GraphInlineMetadata, - context: NodeHandlerContext, - descriptor: NodeDescriptor, - result: TraversalResult, - path: number[], - state: RunState = [] -): Promise => { - // If we have no way to bubble up inputs, we just return and not - // enforce required inputs. - if (!context.requestInput) return; - - const outputs = result.outputs ?? {}; - const reader = new InputSchemaReader(outputs, result.inputs, path); - await context.state?.lifecycle().supplyPartialOutputs(outputs, path); - if (state.length > 0) { - const last = state[state.length - 1]; - if (last.state) { - const unpackedState = loadRunnerState(last.state).state; - unpackedState.partialOutputs = outputs; - last.state = saveRunnerState("nodestart", unpackedState); - } - } - result.outputs = await reader.read( - createBubbleHandler(metadata, context, descriptor, state) - ); -}; - -export const createBubbleHandler = ( - metadata: GraphInlineMetadata, - context: NodeHandlerContext, - descriptor: NodeDescriptor, - state: RunState -) => { - return (async (name, schema, required, path) => { - if (required) { - throw new Error(createErrorMessage(name, metadata, required)); - } - if (schema.default !== undefined) { - if ("type" in schema && schema.type !== "string") { - return JSON.parse(schema.default); - } - return schema.default; - } - const value = await context.requestInput?.( - name, - schema, - descriptor, - path, - state - ); - if (context?.signal?.aborted) { - throw context.signal.throwIfAborted(); - } - if (value === undefined) { - throw new Error(createErrorMessage(name, metadata, required)); - } - return value; - }) satisfies InputSchemaHandler; -}; - -export type InputSchemaHandler = ( - name: string, - schema: Schema, - required: boolean, - path: number[] -) => Promise; - -export class InputSchemaReader { - #currentOutputs: OutputValues; - #inputs: InputValues; - #path: number[]; - - constructor( - currentOutputs: OutputValues, - inputs: InputValues, - path: number[] - ) { - this.#currentOutputs = currentOutputs; - this.#inputs = inputs; - this.#path = path; - } - - async read(handler: InputSchemaHandler): Promise { - if (!("schema" in this.#inputs)) return this.#currentOutputs; - - const schema = this.#inputs.schema as Schema; - - if (!schema.properties) return this.#currentOutputs; - - const entries = Object.entries(schema.properties); - - const newOutputs: OutputValues = {}; - for (const [name, property] of entries) { - if (name in this.#currentOutputs) { - newOutputs[name] = this.#currentOutputs[name]; - continue; - } - const required = schema.required?.includes(name) ?? false; - const value = await handler(name, property, required, this.#path); - newOutputs[name] = value; - } - - return { - ...this.#currentOutputs, - ...newOutputs, - }; - } -} - -export class RequestedInputsManager { - #context: NodeHandlerContext; - #cache: Map = new Map(); - - constructor(args: RunArguments) { - const { inputs, ...context } = args; - this.#context = context; - this.#cache = new Map(inputs ? Object.entries(inputs) : []); - } - - createHandler( - next: (result: RunResult) => Promise, - result: TraversalResult - ) { - return async ( - name: string, - schema: Schema, - node: NodeDescriptor, - path: number[], - state: RunState - ) => { - const cachedValue = this.#cache.get(name); - if (cachedValue !== undefined) return cachedValue; - const descriptor = { id: node.id, type: node.type }; - const requestInputResult = { - ...result, - descriptor, - inputs: { - schema: { type: "object", properties: { [name]: schema } }, - }, - }; - await next(new InputStageResult(requestInputResult, state, -1, path)); - const outputs = requestInputResult.outputs; - let value = outputs && outputs[name]; - if (value === undefined) { - value = await this.#context.requestInput?.( - name, - schema, - descriptor, - path, - state - ); - } - if (!isTransient(schema)) { - this.#cache.set(name, value); - } - return value; - }; - } -} - -const isTransient = (schema: Schema): boolean => { - return schema.behavior?.includes("transient") ?? false; -}; - -export const bubbleUpOutputsIfNeeded = async ( - outputs: OutputValues, - descriptor: NodeDescriptor, - context: NodeHandlerContext, - path: number[] -): Promise => { - if (!context.provideOutput) return false; - const schema = descriptor.configuration?.schema as Schema; - const shouldBubble = schema?.behavior?.includes("bubble"); - if (!shouldBubble) return false; - - await context.provideOutput(outputs, descriptor, path); - return true; -}; - -export const createOutputProvider = ( - next: (result: RunResult) => Promise, - result: TraversalResult, - context: NodeHandlerContext -) => { - if (context.provideOutput) { - return context.provideOutput; - } - return async ( - outputs: OutputValues, - descriptor: NodeDescriptor, - path: number[] - ) => { - const provideOutputResult = { - ...result, - descriptor, - inputs: outputs, - }; - await next(new OutputStageResult(provideOutputResult, -1, path)); - }; -}; diff --git a/packages/breadboard/src/capability.ts b/packages/breadboard/src/capability.ts deleted file mode 100644 index 1807c8a9573..00000000000 --- a/packages/breadboard/src/capability.ts +++ /dev/null @@ -1,162 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { baseURLFromContext } from "./loader/loader.js"; -import { - BreadboardCapability, - GraphDescriptor, - GraphDescriptorBoardCapability, - NodeHandlerContext, - NodeValue, - OutputValues, - ResolvedURLBoardCapability, - UnresolvedPathBoardCapability, -} from "./types.js"; - -// Helpers for BreadboardCapability - -export const isBreadboardCapability = ( - o: unknown -): o is BreadboardCapability => { - const maybe = o as BreadboardCapability; - return !!maybe && maybe.kind === "board"; -}; - -export const isGraphDescriptorCapability = ( - capability: BreadboardCapability -): capability is GraphDescriptorBoardCapability => { - const maybe = capability as GraphDescriptorBoardCapability; - const board = maybe.board; - return !!board && !!board.edges && !!board.nodes; -}; - -export const isResolvedURLBoardCapability = ( - capability: BreadboardCapability -): capability is ResolvedURLBoardCapability => { - const maybe = capability as ResolvedURLBoardCapability; - const url = maybe.url; - return !!url; -}; - -export const isUnresolvedPathBoardCapability = ( - capability: BreadboardCapability -): capability is UnresolvedPathBoardCapability => { - const maybe = capability as UnresolvedPathBoardCapability; - const path = maybe.path; - return !!path; -}; - -const isGraphDescriptor = ( - candidate: unknown -): candidate is GraphDescriptor => { - const graph = candidate as GraphDescriptor; - return ( - graph && typeof graph === "object" && graph.nodes && graph.edges && true - ); -}; - -export const graphDescriptorFromCapability = async ( - capability: BreadboardCapability, - context?: NodeHandlerContext -) => { - if (isGraphDescriptorCapability(capability)) { - // If all we got is a GraphDescriptor, build a runnable board from it. - // TODO: Use JSON schema to validate rather than this hack. - return capability.board; - } else if (isResolvedURLBoardCapability(capability)) { - if (!context?.loader) { - throw new Error( - `The "board" Capability is a URL, but no loader was supplied.` - ); - } - const graph = await context.loader.load(capability.url, context); - if (!graph) { - throw new Error( - `Unable to load "board" Capability with the URL of ${capability.url}.` - ); - } - return graph; - } else if (isUnresolvedPathBoardCapability(capability)) { - if (!context?.loader) { - throw new Error( - `The "board" Capability is a URL, but no loader was supplied.` - ); - } - const graph = await context.loader.load(capability.path, context); - if (!graph) { - throw new Error( - `Unable to load "board" Capability with the path of ${capability.path}.` - ); - } - return graph; - } - throw new Error( - `Unsupported type of "board" Capability. Perhaps the supplied board isn't actually a GraphDescriptor?` - ); -}; - -// TODO: Maybe this is just a GraphLoader API? Instead of taking a `string`, -// the `load` method should take an `unknown` that it then tries to -// shape-detect? And this is the code to do it. -export const getGraphDescriptor = async ( - board: unknown, - context?: NodeHandlerContext -): Promise => { - if (!board) return undefined; - - if (typeof board === "string") { - const graph = await context?.loader?.load(board, context); - if (!graph) throw new Error(`Unable to load graph from "${board}"`); - return graph; - } else if (isBreadboardCapability(board)) { - return graphDescriptorFromCapability(board, context); - } else if (isGraphDescriptor(board)) { - return board; - } - return undefined; -}; - -const resolvePath = ( - capability: UnresolvedPathBoardCapability, - base: URL -): ResolvedURLBoardCapability => { - const path = capability.path; - const url = new URL(path, base).href; - return { kind: "board", url: url }; -}; - -/** - * Resolves any BreadboardCapability instances that are - * `UnresolvedPathBoardCapability` to `ResolvedURLBoardCapability`. - * This must happen at run-time, at the earliest moment when - * the inputs are received by the BoardRunner. - */ -export const resolveBoardCapabilities = async ( - outputs: OutputValues, - context: NodeHandlerContext, - url?: string -): Promise => { - resolveBoardCapabilitiesInInputs(outputs, context, url); - return Promise.resolve(outputs); -}; - -export const resolveBoardCapabilitiesInInputs = ( - values: Record, - context: NodeHandlerContext, - url?: string -) => { - for (const name in values) { - const property = values[name]; - if ( - isBreadboardCapability(property) && - isUnresolvedPathBoardCapability(property) - ) { - const base = url ? new URL(url) : baseURLFromContext(context); - values[name] = resolvePath(property, base); - } - } - return values; -}; diff --git a/packages/breadboard/src/data/common.ts b/packages/breadboard/src/data/common.ts deleted file mode 100644 index 6e8c0ee95b7..00000000000 --- a/packages/breadboard/src/data/common.ts +++ /dev/null @@ -1,177 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - FunctionCallCapabilityPart, - FunctionResponseCapabilityPart, - InlineDataCapabilityPart, - LLMContent, - StoredDataCapabilityPart, - TextCapabilityPart, -} from "./types.js"; -import { DataCapability } from "../types.js"; - -// Helpers for handling DataCapability objects. - -export function isTextCapabilityPart( - part: unknown -): part is TextCapabilityPart { - if (typeof part !== "object" || part === null) return false; - return "text" in part; -} - -export function isFunctionCallCapabilityPart( - part: unknown -): part is FunctionCallCapabilityPart { - if (typeof part !== "object" || part === null) return false; - return "functionCall" in part; -} - -export function isFunctionResponseCapabilityPart( - part: unknown -): part is FunctionResponseCapabilityPart { - if (typeof part !== "object" || part === null) return false; - return "functionResponse" in part; -} - -export function isLLMContent(nodeValue: unknown): nodeValue is LLMContent { - if (typeof nodeValue !== "object" || !nodeValue) return false; - if (nodeValue === null || nodeValue === undefined) return false; - - return "parts" in nodeValue && Array.isArray(nodeValue.parts); -} - -export function isLLMContentArray( - nodeValue: unknown -): nodeValue is LLMContent[] { - if (typeof nodeValue !== "object" || !nodeValue) return false; - if (!Array.isArray(nodeValue)) return false; - if (nodeValue === null || nodeValue === undefined) return false; - - nodeValue = nodeValue.filter((item) => { - if (item === null || item === undefined) return false; - return item.role !== "$metadata"; - }); - - return ( - Array.isArray(nodeValue) && nodeValue.every((entry) => isLLMContent(entry)) - ); -} - -export function isMetadataEntry(nodeValue: LLMContent) { - return nodeValue.role === "$metadata"; -} - -export const isDataCapability = (value: unknown): value is DataCapability => { - if (typeof value !== "object" || value === null) return false; - const data = value as DataCapability; - if (data.kind !== "data") return false; - if ("inlineData" in data) return true; - if ("storedData" in data) return true; - return false; -}; - -export const asBlob = async ( - part: InlineDataCapabilityPart | StoredDataCapabilityPart -) => { - let url: string; - if (isStoredData(part)) { - url = part.storedData.handle; - } else { - url = `data:${part.inlineData.mimeType};base64,${part.inlineData.data}`; - } - const response = await fetch(url); - const data = await response.blob(); - return data; -}; - -export const isStoredData = ( - value: unknown -): value is StoredDataCapabilityPart => { - if (typeof value !== "object" || value === null) return false; - const data = value as DataCapability; - if (!("storedData" in data)) return false; - if (typeof data.storedData.handle !== "string") return false; - return true; -}; - -export const isInlineData = ( - value: unknown -): value is InlineDataCapabilityPart => { - if (typeof value !== "object" || value === null) return false; - const data = value as DataCapability; - if (!("inlineData" in data)) return false; - if (typeof data.inlineData.data !== "string") return false; - return true; -}; - -export const isSerializedData = ( - value: unknown -): value is InlineDataCapabilityPart => { - if (typeof value !== "object" || value === null) return false; - const data = value as DataCapability; - if (!("inlineData" in data)) return false; - if (!("handle" in data)) return false; - if (typeof data.inlineData.data !== "string") return false; - return true; -}; - -export async function asBase64(file: File | Blob): Promise { - if ("Buffer" in globalThis) { - // Node.js implementation, since Node.js doesn't have FileReader. - return Buffer.from(await file.arrayBuffer()).toString("base64"); - } else { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onload = () => { - if (typeof reader.result !== "string") { - reject("Reader result is not a string"); - return; - } - - const [, content] = reader.result.split(","); - resolve(content); - }; - reader.onerror = (err) => reject(err); - reader.readAsDataURL(file); - }); - } -} - -export async function retrieveAsBlob( - part: StoredDataCapabilityPart -): Promise { - if (!isStoredData(part)) { - throw new Error("Invalid stored data"); - } - - const { handle } = part.storedData; - const response = await fetch(handle); - return await response.blob(); -} - -export async function toInlineDataPart( - part: StoredDataCapabilityPart -): Promise { - const raw = await retrieveAsBlob(part); - const mimeType = part.storedData.mimeType; - const data = await asBase64(raw); - return { inlineData: { mimeType, data } }; -} - -export async function toStoredDataPart( - part: InlineDataCapabilityPart | StoredDataCapabilityPart | Blob -): Promise { - const blob = part instanceof Blob ? part : await asBlob(part); - const handle = URL.createObjectURL(blob); - - return { - storedData: { - handle, - mimeType: blob.type, - }, - }; -} diff --git a/packages/breadboard/src/data/default-data-store.ts b/packages/breadboard/src/data/default-data-store.ts deleted file mode 100644 index 833b945760f..00000000000 --- a/packages/breadboard/src/data/default-data-store.ts +++ /dev/null @@ -1,293 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "../harness/types.js"; -import { Schema } from "../types.js"; -import { - asBase64, - toStoredDataPart, - retrieveAsBlob as genericRetrieveAsBlob, - isLLMContentArray, - isMetadataEntry, - isLLMContent, - isInlineData, - isStoredData, -} from "./common.js"; -import { - DataStore, - LLMContent, - RetrieveDataResult, - SerializedDataStoreGroup, - SerializedStoredData, - StoreDataResult, - StoredDataCapabilityPart, -} from "./types.js"; - -export type GroupID = string; -export type NodeTimeStamp = string; -export type OutputProperty = string; -export type OutputPropertyIndex = number; -export type OutputPropertyPartIndex = number; - -type StoredDataEntry = { - value: object | null; - schema: Schema; -}; - -export class DefaultDataStore implements DataStore { - #lastGroupId: string | null = null; - #dataStores = new Map< - GroupID, - Map< - NodeTimeStamp, - Map< - OutputProperty, - Map< - OutputPropertyIndex, - Map - > - > - > - >(); - #keyValueStore = new Map(); - - createGroup(groupId: string) { - let dataStore = this.#dataStores.get(groupId); - if (dataStore) { - throw new Error(`Group with ID already exists: ${groupId}`); - } - - dataStore = new Map< - NodeTimeStamp, - Map< - OutputProperty, - Map< - OutputPropertyIndex, - Map - > - > - >(); - this.#dataStores.set(groupId, dataStore); - this.#lastGroupId = groupId; - } - - async store(blob: Blob, groupId?: string) { - groupId ??= this.#lastGroupId ?? undefined; - if (!groupId) { - throw new Error("No active group - unable to store blob"); - } - - const dataStore = this.#dataStores.get(groupId); - if (!dataStore) { - throw new Error(`No group in data store with ID: ${groupId}`); - } - - const part = await toStoredDataPart(blob); - const nodeTimeStamp = Date.now().toFixed(3); - let properties = dataStore.get(nodeTimeStamp); - if (!properties) { - properties = new Map< - OutputProperty, - Map< - OutputPropertyIndex, - Map - > - >(); - - dataStore.set(nodeTimeStamp, properties); - } - - properties.set( - `direct-set-${nodeTimeStamp}`, - new Map([[0, new Map([[0, part]])]]) - ); - return part; - } - - async retrieveAsBlob(part: StoredDataCapabilityPart): Promise { - return genericRetrieveAsBlob(part); - } - - async replaceDataParts( - groupId: string, - result: HarnessRunResult - ): Promise { - if (result.type !== "nodeend" || result.data.node.type !== "input") { - return; - } - - const dataStore = this.#dataStores.get(groupId); - if (!dataStore) { - throw new Error( - `Unable to replace data parts, no group created for ${groupId}` - ); - } - - const nodeTimeStamp = result.data.timestamp.toFixed(3); - let properties = dataStore.get(nodeTimeStamp); - if (!properties) { - properties = new Map< - OutputProperty, - Map< - OutputPropertyIndex, - Map - > - >(); - dataStore.set(nodeTimeStamp, properties); - } - - for (const [property, value] of Object.entries(result.data.outputs)) { - if (!isLLMContent(value) && !isLLMContentArray(value)) { - continue; - } - - const values: LLMContent[] = isLLMContent(value) ? [value] : value; - - let propertyHandles = properties.get(property); - if (!propertyHandles) { - propertyHandles = new Map< - OutputPropertyIndex, - Map - >(); - properties.set(property, propertyHandles); - } - - for (let i = 0; i < values.length; i++) { - const value = values[i]; - if (isMetadataEntry(value)) { - continue; - } - - for (let j = 0; j < value.parts.length; j++) { - const part = value.parts[j]; - - if (isInlineData(part)) { - let partHandles = propertyHandles.get(0); - if (!partHandles) { - partHandles = new Map< - OutputPropertyIndex, - StoredDataCapabilityPart - >(); - propertyHandles.set(i, partHandles); - } - - let storedDataPart = partHandles.get(j); - if (!storedDataPart) { - storedDataPart = await toStoredDataPart(part); - } - - value.parts[j] = storedDataPart; - partHandles.set(j, storedDataPart); - } else if (isStoredData(part)) { - let partHandles = propertyHandles.get(0); - if (!partHandles) { - partHandles = new Map< - OutputPropertyIndex, - StoredDataCapabilityPart - >(); - propertyHandles.set(i, partHandles); - } - - // This is a stored data from a previous run, so now we need to call - // toStoredDataPart again to create a new stored data part for this - // run. - const storedDataPart = await toStoredDataPart(part); - value.parts[j] = storedDataPart; - partHandles.set(j, storedDataPart); - } - } - } - } - } - - has(groupId: string) { - return this.#dataStores.has(groupId); - } - - async serializeGroup( - groupId: string - ): Promise { - const nodes = this.#dataStores.get(groupId); - if (!nodes) { - return null; - } - - let allHandles: Promise[] = []; - for (const nodeTimeStamp of nodes.values()) { - for (const outputProperty of nodeTimeStamp.values()) { - for (const outputPropertyIndex of outputProperty.values()) { - const storedData = outputPropertyIndex.values(); - allHandles = [...storedData].map(async (storedDataPart) => { - const { handle } = storedDataPart.storedData; - const response = await fetch(handle); - const blob = await response.blob(); - const mimeType = blob.type; - const data = await asBase64(blob); - return { handle, inlineData: { mimeType, data } }; - }); - } - } - } - - return Promise.all(allHandles); - } - - releaseGroup(groupId: string): void { - const nodes = this.#dataStores.get(groupId); - if (!nodes) { - return; - } - - for (const nodeTimeStamp of nodes.values()) { - for (const outputProperty of nodeTimeStamp.values()) { - for (const outputPropertyIndex of outputProperty.values()) { - for (const storedData of outputPropertyIndex.values()) { - URL.revokeObjectURL(storedData.storedData.handle); - } - } - } - } - - this.#dataStores.delete(groupId); - - if (this.#lastGroupId === groupId) { - this.#lastGroupId = null; - } - } - - releaseAll(): void { - for (const groupId of this.#dataStores.keys()) { - this.releaseGroup(groupId); - } - - this.#lastGroupId = null; - } - - async drop(): Promise { - this.releaseAll(); - this.#dataStores.clear(); - return; - } - - async storeData( - key: string, - value: object | null, - schema: Schema - ): Promise { - // TODO: Implement scope handling. - // Corresponds to the "session" scope. - this.#keyValueStore.set(key, { value, schema }); - return { success: true }; - } - - async retrieveData(key: string): Promise { - const entry = this.#keyValueStore.get(key); - if (!entry) { - return { success: false, error: `No value found for key: ${key}` }; - } - return { success: true, value: entry.value, schema: entry.schema }; - } -} diff --git a/packages/breadboard/src/data/default-run-store.ts b/packages/breadboard/src/data/default-run-store.ts deleted file mode 100644 index b629758a54c..00000000000 --- a/packages/breadboard/src/data/default-run-store.ts +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "../harness/types.js"; -import { - isLLMContent, - isLLMContentArray, - isMetadataEntry, - isStoredData, - toInlineDataPart, -} from "./common.js"; -import { RunStore, RunTimestamp, RunURL } from "./types.js"; - -export class DefaultRunStore implements RunStore { - #runs = new Map>(); - - async start(url: RunURL): Promise { - const timestamp = Date.now(); - let store = this.#runs.get(url); - if (!store) { - store = new Map(); - } - - if (store.has(timestamp)) { - throw new Error("Run by name has already started"); - } - - store.set(timestamp, []); - this.#runs.set(url, store); - return timestamp; - } - - async write(url: RunURL, timestamp: RunTimestamp, result: HarnessRunResult) { - const store = this.#runs.get(url); - if (!store) { - throw new Error("Unable to find the store"); - } - - // Before storing any inputs, check if they are using StoredDataParts. - // If so inflate them back to inlineData before storage. - if (result.type === "nodeend" && result.data.node.type === "input") { - for (const output of Object.values(result.data.outputs)) { - if (!isLLMContent(output) && !isLLMContentArray(output)) { - continue; - } - - const outputs = isLLMContent(output) ? [output] : output; - for (const output of outputs) { - if (isMetadataEntry(output)) { - continue; - } - - for (let i = 0; i < output.parts.length; i++) { - const part = output.parts[i]; - if (!isStoredData(part)) { - continue; - } - - output.parts[i] = await toInlineDataPart(part); - } - } - } - } - - const run = store.get(timestamp); - if (!run) { - console.warn(`No run created for timestamp ${timestamp}`); - return; - } - - run.push(result); - } - - async stop(_storeId: RunURL, _timestamp: RunTimestamp) { - // Noop. - } - - async abort(_storeId: RunURL, _timestamp: RunTimestamp) { - // Noop - } - - async drop(url?: RunURL, _limit?: number) { - if (url) { - this.#runs.delete(url); - } else { - this.#runs.clear(); - } - } - - async truncate(url: RunURL, limit: number) { - const store = this.#runs.get(url); - if (!store) { - return; - } - - if (store.size <= limit) { - return; - } - - const toRemove = [...store.keys()].sort((a, b) => b - a).slice(limit); - for (const item of toRemove) { - store.delete(item); - } - } - - async getStoredRuns( - url: RunURL - ): Promise> { - if (!this.#runs.has(url)) { - return new Map(); - } - - return this.#runs.get(url)!; - } -} diff --git a/packages/breadboard/src/data/index.ts b/packages/breadboard/src/data/index.ts deleted file mode 100644 index c0538677239..00000000000 --- a/packages/breadboard/src/data/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { DefaultRunStore } from "./default-run-store.js"; -import { DefaultDataStore } from "./default-data-store.js"; -import { DataStore, RunStore } from "./types.js"; - -export const createDefaultDataStore = (): DataStore => { - return new DefaultDataStore(); -}; - -export const createDefaultRunStore = (): RunStore => { - return new DefaultRunStore(); -}; - -export { inflateData, deflateData } from "./inflate-deflate.js"; - -export { - isFunctionCallCapabilityPart, - isFunctionResponseCapabilityPart, - isLLMContent, - isLLMContentArray, - isTextCapabilityPart, - isDataCapability, - isInlineData, - isStoredData, - isSerializedData, - isMetadataEntry, - asBlob, - asBase64, - toInlineDataPart, - toStoredDataPart, -} from "./common.js"; - -export type { - DataStore, - FunctionCallCapabilityPart, - FunctionResponseCapabilityPart, - LLMContent, - TextCapabilityPart, - StoredDataCapabilityPart, - InlineDataCapabilityPart, -} from "./types.js"; diff --git a/packages/breadboard/src/data/inflate-deflate.ts b/packages/breadboard/src/data/inflate-deflate.ts deleted file mode 100644 index 5c5fac42807..00000000000 --- a/packages/breadboard/src/data/inflate-deflate.ts +++ /dev/null @@ -1,135 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { asBase64, asBlob, isInlineData, isStoredData } from "./common.js"; -import { - DataStore, - InlineDataCapabilityPart, - SerializedDataStoreGroup, -} from "./types.js"; - -/** - * Recursively descends into the data object and inflates any - * `StoreDataCapabilityPart`, turning it into - * `InlineDataCapabilityPart`. - * @param data -- data to inflate - * @returns -- a new object with all `StoredDataCapabilityPart` - * replaced with `InlineDataCapabilityPart` - */ -export const inflateData = async (store: DataStore, data: unknown) => { - const descender = async (value: unknown): Promise => { - if (isStoredData(value)) { - const blob = await store.retrieveAsBlob(value); - const data = await asBase64(blob); - const mimeType = blob.type; - return { inlineData: { data, mimeType } }; - } - if (Array.isArray(value)) { - const result = []; - for (const item of value) { - result.push(await descender(item)); - } - return result; - } - if (typeof value === "object" && value !== null) { - const v = value as Record; - const result: Record = {}; - for (const key in value) { - result[key] = await descender(v[key]); - } - return result; - } - return value; - }; - - const result = await descender(data); - return result; -}; - -/** - * Recursively descends into the data object and deflates any - * `InlineDataCapabilityPart`, turning it into - * `StoredDataCapabilityPart`. - * @param data -- data to deflate - * @returns -- a new object with all `InlineDataCapabilityPart` - * replaced with `StoredDataCapabilityPart` - */ -export const deflateData = async (store: DataStore, data: unknown) => { - const descender = async (value: unknown): Promise => { - if (isInlineData(value)) { - const { mimeType, data } = value.inlineData; - const blob = await fetch(`data:${mimeType};base64,${data}`).then((r) => - r.blob() - ); - return await store.store(blob); - } - if (Array.isArray(value)) { - const result = []; - for (const item of value) { - result.push(await descender(item)); - } - return result; - } - if (typeof value === "object" && value !== null) { - const v = value as Record; - const result: Record = {}; - for (const key in value) { - result[key] = await descender(v[key]); - } - return result; - } - return value; - }; - - const result = await descender(data); - return result; -}; - -/** - * Recursively descends into the data object and replaces any - * instances of `StoredDataCapabilityPart` with another `StoredDataCapabilityPart`, using `SerializedDataStoreGroup` to map between the two. - */ -export const remapData = async ( - store: DataStore, - o: unknown, - serializedData: SerializedDataStoreGroup -) => { - const handleMap = new Map(); - for (const item of serializedData) { - const { handle } = item; - handleMap.set(handle, item); - } - const descender = async (value: unknown): Promise => { - if (isStoredData(value)) { - const { handle } = value.storedData; - const serialized = handleMap.get(handle); - if (!serialized) { - throw new Error(`Could not find serialized data for handle: ${handle}`); - } - const blob = await asBlob(serialized); - return store.store(blob); - } - if (Array.isArray(value)) { - const result = []; - for (const item of value) { - result.push(await descender(item)); - } - return result; - } - if (typeof value === "object" && value !== null) { - const v = value as Record; - const result: Record = {}; - for (const key in value) { - result[key] = await descender(v[key]); - } - return result; - } - return value; - }; - - const result = await descender(o); - return result; -}; diff --git a/packages/breadboard/src/data/types.ts b/packages/breadboard/src/data/types.ts deleted file mode 100644 index 782deb5f5b7..00000000000 --- a/packages/breadboard/src/data/types.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "../harness/types.js"; -import { ReanimationState } from "../run/types.js"; -import { Schema } from "../types.js"; - -export type FunctionCallCapabilityPart = { - functionCall: { - name: string; - args: object; - }; -}; - -export type FunctionResponseCapabilityPart = { - functionResponse: { - name: string; - response: object; - }; -}; - -export type TextCapabilityPart = { - text: string; -}; - -export type DataPart = - | InlineDataCapabilityPart - | StoredDataCapabilityPart - | FunctionCallCapabilityPart - | FunctionResponseCapabilityPart - | TextCapabilityPart; - -export type LLMContent = { - role?: string; - parts: DataPart[]; -}; - -/** - * Represents inline data, encoded as a base64 string. - */ -export type InlineDataCapabilityPart = { - inlineData: { - mimeType: string; - data: string; - }; -}; - -/** - * Represents data that is stored by a DataStoreProvider. - */ -export type StoredDataCapabilityPart = { - storedData: { - handle: DataStoreHandle; - mimeType: string; - }; -}; - -export type DataStoreHandle = string; - -export type StoredData = { - asInline(): Promise; -}; - -export type SerializedStoredData = { - handle: DataStoreHandle; -} & InlineDataCapabilityPart; - -export type SerializedDataStoreGroup = SerializedStoredData[]; - -/** - * A provider that handles storing and retrieving data. - */ - -export type RunURL = string; -export type RunTimestamp = number; - -export type DataStoreProvider = { - store(data: InlineDataCapabilityPart): Promise; - retrieve(handle: DataStoreHandle): Promise; - release(handle: DataStoreHandle): Promise; - releaseAll(): Promise; -}; - -export type RunStore = { - start(url: RunURL): Promise; - write( - url: RunURL, - timestamp: RunTimestamp, - result: HarnessRunResult - ): Promise; - stop(url: RunURL, timestamp: RunTimestamp): Promise; - abort(url: RunURL, timestamp: RunTimestamp): Promise; - drop(url?: RunURL): Promise; - truncate(url: RunURL, limit: number): Promise; - getStoredRuns(url: RunURL): Promise>; -}; - -export type DataStore = { - createGroup(groupId: string): void; - drop(): Promise; - has(groupId: string): boolean; - releaseAll(): void; - releaseGroup(group: string): void; - replaceDataParts(key: string, result: HarnessRunResult): Promise; - retrieveAsBlob(part: StoredDataCapabilityPart): Promise; - serializeGroup( - group: string, - storeId?: string - ): Promise; - store(blob: Blob, storeId?: string): Promise; - /** - * Store a value for later use. - * - * @param key -- the key to store the value under - * @param value -- the value to store, including null - * @param schema -- the schema of the data to store - * @param scope -- the scope to store the data in - */ - storeData( - key: string, - value: object | null, - schema: Schema, - scope: DataStoreScope - ): Promise; - retrieveData(key: string): Promise; -}; - -export type StateStore = { - load(key?: string): Promise; - save(state: ReanimationState): Promise; -}; - -export type StoreDataResult = - | { - success: true; - } - | { - success: false; - error: string; - }; - -export type RetrieveDataResult = - | { - success: true; - value: object | null; - schema: Schema; - } - | { - success: false; - error: string; - }; - -export type DataStoreScope = "run" | "session" | "client"; diff --git a/packages/breadboard/src/editor/blank.ts b/packages/breadboard/src/editor/blank.ts deleted file mode 100644 index b5337ead0c2..00000000000 --- a/packages/breadboard/src/editor/blank.ts +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphTag } from "@google-labs/breadboard-schema/graph.js"; -import { GraphDescriptor, Schema } from "../types.js"; - -const CONFIGURATION = { - schema: { - type: "object", - properties: { - text: { - type: "string", - title: "text", - }, - }, - }, -}; - -const llmContentConfig = (type: string) => ({ - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: - type === "input" ? '[{"role":"user","parts":[{"text":""}]}]' : "null", - }, - }, - type: "object", - required: [], - } satisfies Schema, -}); - -const BLANK_GRAPH: GraphDescriptor = { - title: "Blank board", - description: "A blank board. Use it as a starting point for your creations.", - version: "0.0.1", - nodes: [ - { type: "input", id: "input", configuration: CONFIGURATION }, - { type: "output", id: "output", configuration: CONFIGURATION }, - ], - edges: [{ from: "input", out: "text", to: "output", in: "text" }], -}; - -const BLANK_LLM_CONTENT_GRAPH: GraphDescriptor = { - title: "Blank board", - description: "A blank board. Use it as a starting point for your creations.", - version: "0.0.1", - nodes: [ - { type: "input", id: "input", configuration: llmContentConfig("input") }, - { type: "output", id: "output", configuration: llmContentConfig("output") }, - ], - edges: [{ from: "input", out: "context", to: "output", in: "context" }], -}; - -/** - * Creates a `GraphDescriptor` of a blank graph. - */ -export const blank = (): GraphDescriptor => { - return structuredClone(BLANK_GRAPH); -}; - -/** - * Creates a `GraphDescriptor` of a blank graph with inputs/outputs pre-set - * to the LLM content array schema. - */ -export const blankLLMContent = (...tags: GraphTag[]): GraphDescriptor => { - const graph = structuredClone(BLANK_LLM_CONTENT_GRAPH); - if (tags.length) { - graph.metadata = { tags }; - } - return graph; -}; diff --git a/packages/breadboard/src/editor/edge.ts b/packages/breadboard/src/editor/edge.ts deleted file mode 100644 index de66ecf081e..00000000000 --- a/packages/breadboard/src/editor/edge.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; -import { EditableEdgeSpec } from "./types.js"; - -export const findEdgeIndex = ( - graph: GraphDescriptor, - spec: EditableEdgeSpec -) => { - return graph.edges.findIndex((edge) => { - return edgesEqual(spec, edge); - }); -}; - -export const edgesEqual = (a: EditableEdgeSpec, b: EditableEdgeSpec) => { - return ( - a.from === b.from && - a.to === b.to && - a.out === b.out && - a.in === b.in && - b.constant === b.constant - ); -}; diff --git a/packages/breadboard/src/editor/edit.ts b/packages/breadboard/src/editor/edit.ts deleted file mode 100644 index 523484a513d..00000000000 --- a/packages/breadboard/src/editor/edit.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; -import { InspectableGraph } from "../inspector/types.js"; -import { EditSpec } from "./types.js"; - -/** - * Represents an edit operation. - */ -export class Edit { - #edits: EditSpec[]; - #graph: GraphDescriptor; - #inspector: InspectableGraph; - - constructor( - edits: EditSpec[], - graph: GraphDescriptor, - inspector: InspectableGraph - ) { - this.#edits = edits; - this.#graph = graph; - this.#inspector = inspector; - } -} diff --git a/packages/breadboard/src/editor/events.ts b/packages/breadboard/src/editor/events.ts deleted file mode 100644 index abc90493812..00000000000 --- a/packages/breadboard/src/editor/events.ts +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "../types.js"; -import { - ChangeEventType, - ErrorRejection, - GraphChangeEvent, - GraphChangeRejectEvent, - NoChangeRejection, -} from "./types.js"; - -/** - * This event is dispatched whenever the graph changes due to edits. - */ -export class ChangeEvent extends Event implements GraphChangeEvent { - static eventName = "graphchange"; - - constructor( - public graph: GraphDescriptor, - public version: number, - public visualOnly: boolean, - public changeType: ChangeEventType - ) { - super(ChangeEvent.eventName, { - bubbles: false, - cancelable: true, - composed: true, - }); - } -} - -/** - * This event is dispatched whenever a proposed change to the graph is - * rejected. The rejection may happen for two reasons - * - error: the change would create an invalid graph. For instance, adding an edge to a non-existent node. - * - nochange: the change is unnecessary, because it results in no actual change to the graph. For example, adding an edge that already exists. - */ -export class ChangeRejectEvent extends Event implements GraphChangeRejectEvent { - static eventName = "graphchangereject"; - - constructor( - public graph: GraphDescriptor, - public reason: ErrorRejection | NoChangeRejection - ) { - super(ChangeRejectEvent.eventName, { - bubbles: false, - cancelable: true, - composed: true, - }); - } -} diff --git a/packages/breadboard/src/editor/graph.ts b/packages/breadboard/src/editor/graph.ts deleted file mode 100644 index 0f0d51cb3c8..00000000000 --- a/packages/breadboard/src/editor/graph.ts +++ /dev/null @@ -1,312 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { inspectableGraph } from "../inspector/graph.js"; -import { InspectableGraphWithStore } from "../inspector/types.js"; -import { GraphDescriptor, GraphIdentifier } from "../types.js"; -import { - SingleEditResult, - EditableGraph, - EditableGraphOptions, - RejectionReason, - EditSpec, - EditResult, - EditOperation, - EditOperationContext, - EditResultLogEntry, - EditHistory, -} from "./types.js"; -import { ChangeEvent, ChangeRejectEvent } from "./events.js"; -import { AddEdge } from "./operations/add-edge.js"; -import { AddNode } from "./operations/add-node.js"; -import { RemoveNode } from "./operations/remove-node.js"; -import { RemoveEdge } from "./operations/remove-edge.js"; -import { ChangeEdge } from "./operations/change-edge.js"; -import { ChangeConfiguration } from "./operations/change-configuration.js"; -import { ChangeMetadata } from "./operations/change-metadata.js"; -import { ChangeGraphMetadata } from "./operations/change-graph-metadata.js"; -import { GraphEditHistory } from "./history.js"; - -const operations = new Map([ - ["addnode", new AddNode()], - ["removenode", new RemoveNode()], - ["addedge", new AddEdge()], - ["removeedge", new RemoveEdge()], - ["changeedge", new ChangeEdge()], - ["changeconfiguration", new ChangeConfiguration()], - ["changemetadata", new ChangeMetadata()], - ["changegraphmetadata", new ChangeGraphMetadata()], -]); - -export class Graph implements EditableGraph { - #version = 0; - #options: EditableGraphOptions; - #inspector: InspectableGraphWithStore; - #graph: GraphDescriptor; - #parent: Graph | null; - #graphs: Record | null; - #eventTarget: EventTarget = new EventTarget(); - #history: GraphEditHistory; - - constructor( - graph: GraphDescriptor, - options: EditableGraphOptions, - parent: Graph | null - ) { - this.#graph = graph; - this.#parent = parent || null; - if (parent) { - // Embedded subgraphs can not have subgraphs. - this.#graphs = null; - } else { - this.#graphs = Object.fromEntries( - Object.entries(graph.graphs || {}).map(([id, graph]) => [ - id, - new Graph(graph, options, this), - ]) - ); - } - this.#options = options; - this.#version = parent ? 0 : options.version || 0; - this.#inspector = inspectableGraph(this.#graph, options); - this.#history = new GraphEditHistory({ - graph: () => { - return this.#graph; - }, - version: () => { - return this.#version; - }, - setGraph: (graph) => { - this.#graph = graph; - this.#version++; - this.#inspector.resetGraph(graph); - this.#eventTarget.dispatchEvent( - new ChangeEvent(this.#graph, this.#version, false, "history") - ); - }, - }); - this.#history.add(graph, "Clean slate"); - } - - #makeIndependent() { - this.#parent = null; - this.#graphs = {}; - } - - #updateGraph(visualOnly: boolean) { - if (this.#parent) { - this.#graph = { ...this.#graph }; - // Update parent version. - this.#parent.#updateGraph(visualOnly); - } else { - if (!this.#graphs) { - throw new Error( - "Integrity error: a supergraph with no ability to add subgraphs" - ); - } - const entries = Object.entries(this.#graphs); - if (entries.length === 0) { - if ("graphs" in this.#graph) delete this.#graph["graphs"]; - this.#graph = { ...this.#graph }; - } else { - const graphs = Object.fromEntries( - entries.map(([id, graph]) => [id, graph.raw()]) - ); - this.#graph = { ...this.#graph, graphs }; - } - this.#version++; - } - this.#inspector.updateGraph(this.#graph); - this.#eventTarget.dispatchEvent( - new ChangeEvent(this.#graph, this.#version, visualOnly, "edit") - ); - } - - #rollbackGraph(checkpoint: GraphDescriptor, error: string) { - this.#graph = checkpoint; - // TODO: Handle subgraphs. - this.#inspector.resetGraph(this.#graph); - this.#dispatchNoChange(error); - } - - #dispatchNoChange(error?: string) { - if (this.#parent) { - this.#parent.#dispatchNoChange(error); - } - this.#graph = { ...this.#graph }; - const reason: RejectionReason = error - ? { - type: "error", - error, - } - : { - type: "nochange", - }; - this.#eventTarget.dispatchEvent(new ChangeRejectEvent(this.#graph, reason)); - } - - addEventListener(eventName: string, listener: EventListener): void { - this.#eventTarget.addEventListener(eventName, listener); - } - - version() { - if (this.#parent) { - throw new Error("Embedded subgraphs can not be versioned."); - } - return this.#version; - } - - parent() { - return this.#parent; - } - - async #singleEdit( - edit: EditSpec, - context: EditOperationContext - ): Promise { - const operation = operations.get(edit.type); - if (!operation) { - return { - success: false, - error: "Unsupported edit type", - }; - } - return operation.do(edit, context); - } - - async edit( - edits: EditSpec[], - label: string, - dryRun = false - ): Promise { - let context: EditOperationContext; - - const checkpoint = structuredClone(this.#graph); - if (dryRun) { - const graph = checkpoint; - const inspector = inspectableGraph(graph, this.#options); - context = { - graph, - inspector, - store: inspector, - }; - } else { - context = { - graph: this.#graph, - inspector: this.#inspector, - store: this.#inspector, - }; - } - const log: EditResultLogEntry[] = []; - let error: string | null = null; - // Presume that all edits will result in no changes. - let noChange = true; - // Presume that all edits will be visual only. - let visualOnly = true; - for (const edit of edits) { - const result = await this.#singleEdit(edit, context); - log.push({ edit: edit.type, result }); - if (!result.success) { - error = result.error; - break; - } - if (!result.noChange) { - noChange = false; - } - if (!result.visualOnly) { - visualOnly = false; - } - } - if (error) { - !dryRun && this.#rollbackGraph(checkpoint, error); - return { success: false, log, error }; - } - - if (noChange) { - !dryRun && this.#dispatchNoChange(); - return { success: true, log }; - } - - this.#history.addEdit(this.#graph, checkpoint, label, this.#version); - - !dryRun && this.#updateGraph(visualOnly); - return { success: true, log }; - } - - history(): EditHistory { - return this.#history; - } - - getGraph(id: GraphIdentifier) { - if (!this.#graphs) { - throw new Error("Embedded graphs can't contain subgraphs."); - } - return this.#graphs[id] || null; - } - - addGraph(id: GraphIdentifier, graph: GraphDescriptor): EditableGraph | null { - if (!this.#graphs) { - throw new Error("Embedded graphs can't contain subgraphs."); - } - - if (this.#graphs[id]) { - return null; - } - - const editable = new Graph(graph, this.#options, this); - this.#graphs[id] = editable; - this.#updateGraph(false); - - return editable; - } - - removeGraph(id: GraphIdentifier): SingleEditResult { - if (!this.#graphs) { - throw new Error("Embedded graphs can't contain subgraphs."); - } - - if (!this.#graphs[id]) { - const error = `Subgraph with id "${id}" does not exist`; - this.#dispatchNoChange(error); - return { - success: false, - error, - }; - } - delete this.#graphs[id]; - this.#updateGraph(false); - return { success: true }; - } - - replaceGraph( - id: GraphIdentifier, - graph: GraphDescriptor - ): EditableGraph | null { - if (!this.#graphs) { - throw new Error("Embedded graphs can't contain subgraphs."); - } - - const old = this.#graphs[id]; - if (!old) { - return null; - } - old.#makeIndependent(); - - const editable = new Graph(graph, this.#options, this); - this.#graphs[id] = editable; - this.#updateGraph(false); - - return editable; - } - - raw() { - return this.#graph; - } - - inspect() { - return this.#inspector; - } -} diff --git a/packages/breadboard/src/editor/history.ts b/packages/breadboard/src/editor/history.ts deleted file mode 100644 index 84a812ce40b..00000000000 --- a/packages/breadboard/src/editor/history.ts +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "../types.js"; -import { - EditHistory, - EditHistoryController, - EditHistoryEntry, -} from "./types.js"; - -export class GraphEditHistory implements EditHistory { - #controller: EditHistoryController; - #history: EditHistoryManager = new EditHistoryManager(); - - constructor(controller: EditHistoryController) { - this.#controller = controller; - } - - add(graph: GraphDescriptor, label: string) { - this.#history.add(graph, label); - } - - addEdit( - graph: GraphDescriptor, - checkpoint: GraphDescriptor, - label: string, - version: number - ) { - this.#history.pause(label, checkpoint, version); - - this.#history.add(graph, label); - } - - canUndo(): boolean { - return this.#history.canGoBack(); - } - - canRedo(): boolean { - return this.#history.canGoForth(); - } - - undo(): void { - this.#history.resume(this.#controller.graph(), this.#controller.version()); - const graph = this.#history.back(); - if (!graph) return; - this.#controller.setGraph(graph); - } - - redo(): void { - this.#history.resume(this.#controller.graph(), this.#controller.version()); - const graph = this.#history.forth(); - if (!graph) return; - this.#controller.setGraph(graph); - } - - entries(): EditHistoryEntry[] { - return this.#history.history; - } - - index(): number { - return this.#history.index(); - } -} - -export class EditHistoryManager { - history: EditHistoryEntry[] = []; - #index: number = 0; - pauseLabel: string | null = null; - #version: number = 0; - - current(): GraphDescriptor | null { - const entry = this.history[this.#index]; - if (!entry) return null; - return structuredClone(entry.graph); - } - - index() { - return this.#index; - } - - add(graph: GraphDescriptor, label: string) { - if (this.paused()) return; - // Chop off the history at #index. - this.history.splice(this.#index + 1); - // Insert new entry. - this.history.push({ graph: structuredClone(graph), label }); - // Point #index the new entry. - this.#index = this.history.length - 1; - } - - canGoBack(): boolean { - return this.#index > 0; - } - - canGoForth(): boolean { - return this.#index < this.history.length - 1; - } - - back(): GraphDescriptor | null { - if (this.paused()) return null; - this.#index && this.#index--; - return this.current(); - } - - forth(): GraphDescriptor | null { - if (this.paused()) return null; - const newIndex = this.#index + 1; - const maxIndex = this.history.length - 1; - if (newIndex <= maxIndex) { - this.#index = newIndex; - } - return this.current(); - } - - paused() { - return this.pauseLabel !== null; - } - - pause(label: string, graph: GraphDescriptor, version: number) { - if (this.pauseLabel !== label) { - this.resume(graph, version); - } - this.pauseLabel = label; - this.#version = version; - } - - resume(graph: GraphDescriptor, version: number) { - if (this.pauseLabel === null) return; - const label = this.pauseLabel; - this.pauseLabel = null; - if (this.#version !== version) { - this.add(graph, label); - } - } -} diff --git a/packages/breadboard/src/editor/index.ts b/packages/breadboard/src/editor/index.ts deleted file mode 100644 index 68db6753915..00000000000 --- a/packages/breadboard/src/editor/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "../types.js"; -import { Graph } from "./graph.js"; -import { EditableGraph, EditableGraphOptions } from "./types.js"; - -export const editGraph = ( - graph: GraphDescriptor, - options: EditableGraphOptions = {} -): EditableGraph => { - return new Graph(graph, options, null); -}; - -export { blank, blankLLMContent } from "./blank.js"; diff --git a/packages/breadboard/src/editor/operations/add-edge.ts b/packages/breadboard/src/editor/operations/add-edge.ts deleted file mode 100644 index cd49402dd87..00000000000 --- a/packages/breadboard/src/editor/operations/add-edge.ts +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - EditOperation, - EditOperationContext, - EditSpec, - EditableEdgeSpec, - SingleEditResult, -} from "../types.js"; -import { InspectableGraph } from "../../inspector/types.js"; -import { - fixUpStarEdge, - fixupConstantEdge, - unfixUpStarEdge, -} from "../../inspector/edge.js"; - -export class AddEdge implements EditOperation { - async can( - edge: EditableEdgeSpec, - inspector: InspectableGraph - ): Promise { - edge = unfixUpStarEdge(edge); - if (inspector.hasEdge(edge)) { - return { - success: false, - error: `Edge from "${edge.from}:${edge.out}" to "${edge.to}:${edge.in}" already exists`, - }; - } - const from = inspector.nodeById(edge.from); - if (!from) { - return { - success: false, - error: `Node with id "${edge.from}" does not exist, but is required as the "from" part of the edge`, - }; - } - const to = inspector.nodeById(edge.to); - if (!to) { - return { - success: false, - error: `Node with id "${edge.to}" does not exist, but is required as the "to" part of the edge`, - }; - } - - let error: string | null = null; - if (edge.out === "*" && edge.in !== "*") { - error = `A "*" output port cannot be connected to a named or control input port`; - } else if (edge.out === "" && edge.in !== "") { - error = `A control input port cannot be connected to a named or "*" output part`; - } else if (edge.in === "*" && edge.out !== "*") { - error = `A named input port cannot be connected to a "*" output port`; - } else if (edge.in === "" && edge.out !== "") { - error = `A named input port cannot be connected to a control output port`; - } - if (error) { - return { success: false, error }; - } - - const fromPorts = (await from.ports()).outputs; - if (fromPorts.fixed) { - const found = fromPorts.ports.find((port) => port.name === edge.out); - if (!found) { - error ??= `Node with id "${edge.from}" does not have an output port named "${edge.out}"`; - return { - success: false, - error, - }; - } - } - const toPorts = (await to.ports()).inputs; - if (toPorts.fixed) { - const found = toPorts.ports.find((port) => port.name === edge.in); - if (!found) { - error ??= `Node with id "${edge.to}" does not have an input port named "${edge.in}"`; - return { - success: false, - error, - }; - } - } - return { success: true }; - } - - async do( - spec: EditSpec, - context: EditOperationContext - ): Promise { - if (spec.type !== "addedge") { - throw new Error( - `Editor API integrity error: expected type "addedge", received "${spec.type}" instead.` - ); - } - let edge = spec.edge; - const { graph, inspector, store } = context; - const can = await this.can(edge, inspector); - if (!can.success) { - return can; - } - edge = fixUpStarEdge(edge); - edge = fixupConstantEdge(edge); - // TODO: Figure out how to make this work in multi-edit mode. - store.edgeStore.add(edge); - graph.edges.push(edge); - return { success: true }; - } -} diff --git a/packages/breadboard/src/editor/operations/add-node.ts b/packages/breadboard/src/editor/operations/add-node.ts deleted file mode 100644 index 04fe2e94a2a..00000000000 --- a/packages/breadboard/src/editor/operations/add-node.ts +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - EditOperation, - EditOperationContext, - EditSpec, - EditableNodeSpec, - SingleEditResult, -} from "../types.js"; -import { InspectableGraph } from "../../inspector/types.js"; - -export class AddNode implements EditOperation { - async can( - spec: EditableNodeSpec, - inspector: InspectableGraph - ): Promise { - const duplicate = !!inspector.nodeById(spec.id); - if (duplicate) { - return { - success: false, - error: `Unable to add node: a node with id "${spec.id}" already exists`, - }; - } - - const validType = !!inspector.typeById(spec.type); - if (!validType) { - return { - success: false, - error: `Unable to add node: node type "${spec.type}" is not a known type`, - }; - } - - return { success: true }; - } - - async do( - spec: EditSpec, - context: EditOperationContext - ): Promise { - if (spec.type !== "addnode") { - throw new Error( - `Editor API integrity error: expected type "addnode", received "${spec.type}" instead.` - ); - } - const node = spec.node; - const { graph, inspector, store } = context; - const can = await this.can(node, inspector); - if (!can.success) { - return can; - } - - graph.nodes.push(node); - store.nodeStore.add(node); - return { success: true }; - } -} diff --git a/packages/breadboard/src/editor/operations/change-configuration.ts b/packages/breadboard/src/editor/operations/change-configuration.ts deleted file mode 100644 index e75a3a7ab72..00000000000 --- a/packages/breadboard/src/editor/operations/change-configuration.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { NodeIdentifier } from "@google-labs/breadboard-schema/graph.js"; -import { - EditOperation, - EditOperationContext, - EditSpec, - SingleEditResult, -} from "../types.js"; -import { InspectableGraph } from "../../inspector/types.js"; - -export class ChangeConfiguration implements EditOperation { - async can( - id: NodeIdentifier, - inspector: InspectableGraph - ): Promise { - const node = inspector.nodeById(id); - if (!node) { - return { - success: false, - error: `Unable to update configuration: node with id "${id}" does not exist`, - }; - } - return { success: true }; - } - - async do( - spec: EditSpec, - context: EditOperationContext - ): Promise { - if (spec.type !== "changeconfiguration") { - throw new Error( - `Editor API integrity error: expected type "changeconfiguration", received "${spec.type}" instead.` - ); - } - const { id, configuration, reset = false } = spec; - if (!configuration) { - return { - success: false, - error: "Configuration wasn't supplied.", - }; - } - const { inspector } = context; - const can = await this.can(id, inspector); - if (!can.success) { - return can; - } - const node = inspector.nodeById(id); - if (node) { - if (reset) { - node.descriptor.configuration = configuration; - } else { - node.descriptor.configuration = { - ...node.descriptor.configuration, - ...configuration, - }; - } - } - return { success: true }; - } -} diff --git a/packages/breadboard/src/editor/operations/change-edge.ts b/packages/breadboard/src/editor/operations/change-edge.ts deleted file mode 100644 index d5729ea2b9a..00000000000 --- a/packages/breadboard/src/editor/operations/change-edge.ts +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { InspectableGraph } from "../../inspector/types.js"; -import { - EditOperation, - EditOperationContext, - EditSpec, - EditableEdgeSpec, - SingleEditResult, -} from "../types.js"; -import { RemoveEdge } from "./remove-edge.js"; -import { AddEdge } from "./add-edge.js"; -import { edgesEqual, findEdgeIndex } from "../edge.js"; -import { fixUpStarEdge } from "../../inspector/edge.js"; - -export class ChangeEdge implements EditOperation { - async can( - from: EditableEdgeSpec, - to: EditableEdgeSpec, - inspector: InspectableGraph - ): Promise { - if (edgesEqual(from, to)) { - return { success: true }; - } - const canRemoveOp = new RemoveEdge(); - const canRemove = await canRemoveOp.can(from, inspector); - if (!canRemove.success) return canRemove; - const canAddOp = new AddEdge(); - const canAdd = await canAddOp.can(to, inspector); - if (!canAdd.success) return canAdd; - return { success: true }; - } - - async do( - spec: EditSpec, - context: EditOperationContext - ): Promise { - if (spec.type !== "changeedge") { - throw new Error( - `Editor API integrity error: expected type "changeedge", received "${spec.type}" instead.` - ); - } - const from = spec.from; - const to = spec.to; - - const { graph, inspector } = context; - const can = await this.can(from, to, inspector); - if (!can.success) { - return can; - } - if (edgesEqual(from, to)) { - return { success: true, noChange: true }; - } - const fixedUpEdge = fixUpStarEdge(from); - const edges = graph.edges; - const index = findEdgeIndex(graph, fixedUpEdge); - const edge = edges[index]; - edge.from = to.from; - edge.out = to.out; - edge.to = to.to; - edge.in = to.in; - if (to.constant === true) { - edge.constant = to.constant; - } - return { success: true }; - } -} diff --git a/packages/breadboard/src/editor/operations/change-graph-metadata.ts b/packages/breadboard/src/editor/operations/change-graph-metadata.ts deleted file mode 100644 index ea67545a366..00000000000 --- a/packages/breadboard/src/editor/operations/change-graph-metadata.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - EditOperation, - EditOperationContext, - EditSpec, - SingleEditResult, -} from "../types.js"; - -export class ChangeGraphMetadata implements EditOperation { - async do( - spec: EditSpec, - context: EditOperationContext - ): Promise { - if (spec.type !== "changegraphmetadata") { - throw new Error( - `Editor API integrity error: expected type "changegraphmetadata", received "${spec.type}" instead.` - ); - } - const { metadata } = spec; - const { graph } = context; - const visualOnly = graph.metadata === metadata; - graph.metadata = metadata; - return { success: true, visualOnly }; - } -} diff --git a/packages/breadboard/src/editor/operations/change-metadata.ts b/packages/breadboard/src/editor/operations/change-metadata.ts deleted file mode 100644 index 22f62393626..00000000000 --- a/packages/breadboard/src/editor/operations/change-metadata.ts +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - NodeIdentifier, - NodeMetadata, -} from "@google-labs/breadboard-schema/graph.js"; -import { - EditOperation, - EditOperationContext, - EditSpec, - SingleEditResult, -} from "../types.js"; -import { InspectableGraph } from "../../inspector/types.js"; - -export class ChangeMetadata implements EditOperation { - async can( - id: NodeIdentifier, - inspector: InspectableGraph - ): Promise { - const node = inspector.nodeById(id); - if (!node) { - return { - success: false, - error: `Unable to change metadata: node with id "${id}" does not exist`, - }; - } - return { success: true }; - } - - #isVisualOnly(incoming: NodeMetadata, existing: NodeMetadata): boolean { - return ( - existing.title === incoming.title && - existing.description === incoming.description && - existing.logLevel === incoming.logLevel - ); - } - - async do( - spec: EditSpec, - context: EditOperationContext - ): Promise { - if (spec.type !== "changemetadata") { - throw new Error( - `Editor API integrity error: expected type "changemetadata", received "${spec.type}" instead.` - ); - } - const { id, metadata, reset = false } = spec; - const { inspector } = context; - const can = await this.can(id, inspector); - if (!can.success) return can; - const node = inspector.nodeById(id); - if (!node) { - const error = `Unknown node with id "${id}"`; - return { success: false, error }; - } - const visualOnly = this.#isVisualOnly( - metadata, - node.descriptor.metadata || {} - ); - const oldMetadata = node.descriptor.metadata; - if (reset) { - node.descriptor.metadata = metadata; - } else { - node.descriptor.metadata = { - ...oldMetadata, - ...metadata, - }; - } - return { success: true, visualOnly }; - } -} diff --git a/packages/breadboard/src/editor/operations/remove-edge.ts b/packages/breadboard/src/editor/operations/remove-edge.ts deleted file mode 100644 index 4b88ae46379..00000000000 --- a/packages/breadboard/src/editor/operations/remove-edge.ts +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - EditOperation, - EditOperationContext, - EditSpec, - EditableEdgeSpec, - SingleEditResult, -} from "../types.js"; -import { InspectableGraph } from "../../inspector/types.js"; -import { fixUpStarEdge } from "../../inspector/edge.js"; -import { findEdgeIndex } from "../edge.js"; - -export class RemoveEdge implements EditOperation { - async can( - spec: EditableEdgeSpec, - inspector: InspectableGraph - ): Promise { - if (!inspector.hasEdge(spec)) { - return { - success: false, - error: `Edge from "${spec.from}:${spec.out}" to "${spec.to}:${spec.in}" does not exist`, - }; - } - return { success: true }; - } - - async do( - spec: EditSpec, - context: EditOperationContext - ): Promise { - if (spec.type !== "removeedge") { - throw new Error( - `Editor API integrity error: expected type "removeedge", received "${spec.type}" instead.` - ); - } - let edge = spec.edge; - const { graph, inspector, store } = context; - const can = await this.can(edge, inspector); - if (!can.success) { - return can; - } - edge = fixUpStarEdge(edge); - const edges = graph.edges; - const index = findEdgeIndex(graph, edge); - const foundEdge = edges.splice(index, 1)[0]; - store.edgeStore.remove(foundEdge); - return { success: true }; - } -} diff --git a/packages/breadboard/src/editor/operations/remove-node.ts b/packages/breadboard/src/editor/operations/remove-node.ts deleted file mode 100644 index 6359cbc479b..00000000000 --- a/packages/breadboard/src/editor/operations/remove-node.ts +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { NodeIdentifier } from "@google-labs/breadboard-schema/graph.js"; -import { - EditOperation, - EditOperationContext, - EditSpec, - SingleEditResult, -} from "../types.js"; -import { InspectableGraph } from "../../inspector/types.js"; - -export class RemoveNode implements EditOperation { - async can( - id: NodeIdentifier, - inspector: InspectableGraph - ): Promise { - const exists = !!inspector.nodeById(id); - if (!exists) { - return { - success: false, - error: `Unable to remove node: node with id "${id}" does not exist`, - }; - } - return { success: true }; - } - - async do( - spec: EditSpec, - context: EditOperationContext - ): Promise { - if (spec.type !== "removenode") { - throw new Error( - `Editor API integrity error: expected type "removenode", received "${spec.type}" instead.` - ); - } - const id = spec.id; - const { graph, inspector, store } = context; - const can = await this.can(id, inspector); - if (!can.success) { - return can; - } - - // Remove any edges that are connected to the removed node. - graph.edges = graph.edges.filter((edge) => { - const shouldRemove = edge.from === id || edge.to === id; - if (shouldRemove) { - store.edgeStore.remove(edge); - } - return !shouldRemove; - }); - // Remove the node from the graph. - graph.nodes = graph.nodes.filter((node) => node.id != id); - store.nodeStore.remove(id); - return { success: true }; - } -} diff --git a/packages/breadboard/src/editor/types.ts b/packages/breadboard/src/editor/types.ts deleted file mode 100644 index 86c23983e9b..00000000000 --- a/packages/breadboard/src/editor/types.ts +++ /dev/null @@ -1,321 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphIdentifier, - GraphMetadata, - NodeMetadata, -} from "@google-labs/breadboard-schema/graph.js"; -import { - GraphStoreMutator, - InspectableGraph, - InspectableGraphOptions, -} from "../inspector/types.js"; -import { - Edge, - GraphDescriptor, - NodeConfiguration, - NodeDescriptor, - NodeIdentifier, -} from "../types.js"; - -export type ChangeEventType = "edit" | "history"; - -export type GraphChangeEvent = Event & { - graph: GraphDescriptor; - version: number; - visualOnly: boolean; - changeType: ChangeEventType; -}; - -export type ErrorRejection = { - type: "error"; - error: string; -}; - -export type NoChangeRejection = { - type: "nochange"; -}; - -export type RejectionReason = ErrorRejection | NoChangeRejection; - -export type GraphChangeRejectEvent = Event & { - graph: GraphDescriptor; - reason: RejectionReason; -}; - -export type EditableGraphEventMap = { - graphchange: GraphChangeEvent; - graphchangereject: GraphChangeRejectEvent; -}; - -export type AddNodeSpec = { - type: "addnode"; - node: EditableNodeSpec; -}; - -export type RemoveNodeSpec = { - type: "removenode"; - id: NodeIdentifier; -}; - -export type AddEdgeSpec = { - type: "addedge"; - edge: EditableEdgeSpec; -}; - -export type RemoveEdgeSpec = { - type: "removeedge"; - edge: EditableEdgeSpec; -}; - -/** - * Changes the edge from `from` to `to`, if it can be changed. - * This operation does not change the identity of the edge, but rather - * mutates the properties of the edge. This is not an `addEdge` combined - * with a `removeEdge`, but rather a true mutation of the edge. - */ -export type ChangeEdgeSpec = { - type: "changeedge"; - from: EditableEdgeSpec; - to: EditableEdgeSpec; -}; - -export type ChangeConfigurationSpec = { - type: "changeconfiguration"; - id: NodeIdentifier; - configuration: NodeConfiguration; - /** - * If set to `true`, the configuration will be set to the value specified in - * `configuration`. If set to `false`, the value will be merged with the - * existing configuration. Defaults to `false`. - */ - reset?: boolean; -}; - -export type ChangeMetadataSpec = { - type: "changemetadata"; - id: NodeIdentifier; - metadata: NodeMetadata; - /** - * If set to `true`, the metadata will be set to the value specified in - * `metadata`. If set to `false`, the value will be merged with the - * existing metadata. Defaults to `false`. - */ - reset?: boolean; -}; - -export type ChangeGraphMetadataSpec = { - type: "changegraphmetadata"; - metadata: GraphMetadata; -}; - -export type AddGraphSpec = { - type: "addgraph"; - id: GraphIdentifier; - graph: GraphDescriptor; -}; - -export type ReplaceGraphSpec = { - type: "replacegraph"; - id: GraphIdentifier; - graph: GraphDescriptor; -}; - -export type RemoveGraphSpec = { - type: "removegraph"; - id: GraphIdentifier; -}; - -export type EditOperationContext = { - graph: GraphDescriptor; - inspector: InspectableGraph; - store: GraphStoreMutator; -}; - -export type EditOperation = { - do(edit: EditSpec, context: EditOperationContext): Promise; -}; - -export type EditSpec = - | AddNodeSpec - | RemoveNodeSpec - | AddEdgeSpec - | RemoveEdgeSpec - | ChangeEdgeSpec - | ChangeConfigurationSpec - | ChangeMetadataSpec - | ChangeGraphMetadataSpec; - -export type EditableGraph = { - addEventListener( - eventName: Key, - listener: ((evt: EditableGraphEventMap[Key]) => void) | null - ): void; - /** - * Returns the current version of the graph. This number increments with - * every edit. - * @throws when used on an embedded subgraph. - */ - version(): number; - - /** - * Returns parent graph, if any. - * This value will be non-null only for graphs (subgraphs) that are embedded - * within a graph. - */ - parent(): EditableGraph | null; - - /** - * Performs an edit operation on the graph. - * @param edits -- a list of changes to apply - * @param label -- a user-friendly description of the edit, which also - * serves a grouping hint for undo/redo operations. - * @param dryRun -- if true, perform the edit, but discard the changes. - */ - edit(edits: EditSpec[], label: string, dryRun?: boolean): Promise; - - /** - * Provides a way to manage the history of the graph. - */ - history(): EditHistory; - - /** - * Retrieves a subgraph of this graph. - * @param id -- id of the subgraph - * @throws when used on an embedded subgraph. - */ - getGraph(id: GraphIdentifier): EditableGraph | null; - /** - * If does not exist already, adds a subgraph with the specified id. - * Fails (returns null) if the subgraph with this id already exists. - * @param id - id of the new subgraph - * @param graph - the subgraph to add - * @returns - the `EditableGraph` instance of the subgraph - * @throws when used on an embedded subgraph. - */ - addGraph(id: GraphIdentifier, graph: GraphDescriptor): EditableGraph | null; - /** - * Replaces the subgraph with the specified id. Fails (returns null) - * if the subgraph with this id does not already exist. - * @param id - id of the subgraph being replaced - * @param graph - the subgraph with which to replace the existing subgraph - * @returns - the `EditableGraph` instance of the newly replaced subgraph. - * @throws when used on an embedded subgraph. - */ - replaceGraph( - id: GraphIdentifier, - graph: GraphDescriptor - ): EditableGraph | null; - /** - * Removes the subgraph with the specified id. Fails if the subgraph does not - * exist. - * @param id - id of the subgraph to remove - * @throws when used on an embedded subgraph. - */ - removeGraph(id: GraphIdentifier): SingleEditResult; - - raw(): GraphDescriptor; - - inspect(): InspectableGraph; -}; - -export type EditHistoryController = { - graph(): GraphDescriptor; - setGraph(graph: GraphDescriptor): void; - version(): number; -}; - -export type EditHistory = { - /** - * Reports whether an undo operation is possible at a given moment. - * The undo may not be possible because we're at the beginning of the - * history. */ - canUndo(): boolean; - - /** - * Reports whether a redo operation is possible at a given moment. - * The redo may not be possible because we're at the end of the history. - */ - canRedo(): boolean; - - /** - * Undoes the last change or does nothing if there isn't one. - */ - undo(): void; - - /** - * Re-does the change that was undone or does nothing if there isn't one. - */ - redo(): void; - - /** - * Returns a list of all entries in the history. - */ - entries(): EditHistoryEntry[]; - - /** - * Current index in the history. - */ - index(): number; -}; - -export type EditHistoryEntry = { graph: GraphDescriptor; label: string }; - -export type EditableGraphOptions = InspectableGraphOptions & { - /** - * The initial version of the graph - */ - version?: number; -}; - -export type EditableNodeSpec = NodeDescriptor; - -export type SingleEditResult = - | { - success: false; - error: string; - /** - * Only used when editing edges, provides an - * alternative that could be used for the operation to still succeed. - */ - alternative?: EditableEdgeSpec; - } - | { - success: true; - /** - * Indicates that the edit was successful, and - * resulted in no change. - */ - noChange?: boolean; - /** - * Indicates that this edit only involved visual - * changes. - */ - visualOnly?: boolean; - }; - -export type EditResultLogEntry = { - edit: EditSpec["type"]; - result: SingleEditResult; -}; - -/** - * Multi-edit result. - */ -export type EditResult = { - log: EditResultLogEntry[]; -} & ( - | { - success: true; - } - | { - success: false; - error: string; - } -); - -export type EditableEdgeSpec = Edge; diff --git a/packages/breadboard/src/handler.ts b/packages/breadboard/src/handler.ts deleted file mode 100644 index 6e13cd3d163..00000000000 --- a/packages/breadboard/src/handler.ts +++ /dev/null @@ -1,212 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { inspect } from "./inspector/index.js"; -import { SENTINEL_BASE_URL } from "./loader/loader.js"; -import { invokeGraph } from "./run/invoke-graph.js"; -import type { - GraphDescriptor, - InputValues, - Kit, - NodeDescriberContext, - NodeDescriberResult, - NodeHandler, - NodeHandlerContext, - NodeHandlerFunction, - NodeHandlerObject, - NodeHandlers, - NodeTypeIdentifier, - OutputValues, -} from "./types.js"; -import { graphUrlLike } from "./utils/graph-url-like.js"; -import { hash } from "./utils/hash.js"; -import { Throttler } from "./utils/throttler.js"; - -const getHandlerFunction = (handler: NodeHandler): NodeHandlerFunction => { - if ("invoke" in handler && handler.invoke) return handler.invoke; - if (handler instanceof Function) return handler; - throw new Error("Invalid handler"); -}; - -export const callHandler = async ( - handler: NodeHandler, - inputs: InputValues, - context: NodeHandlerContext -): Promise => { - // if (handler instanceof Function) return handler(inputs, context); - // if (handler.invoke) return handler.invoke(inputs, context); - const handlerFunction = getHandlerFunction(handler); - return new Promise((resolve) => { - handlerFunction(inputs, context) - .then(resolve) - .catch((error) => { - resolve({ $error: { error } }); - }); - }); -}; - -export const handlersFromKits = (kits: Kit[]): NodeHandlers => { - return kits.reduce((handlers, kit) => { - // If multiple kits have the same handler, the kit earlier in the list - // gets precedence, including upstream kits getting precedence over kits - // defined in the graph. - // - // TODO: This means kits are fallback, consider non-fallback as well. - return { ...kit.handlers, ...handlers }; - }, {} as NodeHandlers); -}; - -/** - * The single entry point for getting a handler for a node type. - * The handler can be one of the two types: - * - A graph-based handler, where the `type` is actually a - * URL-like string that points to a graph. - * - A kit-based handler, where the `type` is a string that - * corresponds to a node type in a kit. - * - * The function throws an error if no handler is found for the - * given node type. - * - * @param type -- The node type to get a handler for. - * @param context -- The context in which the handler is - * being requested. - * @returns -- The handler for the node type. - */ -export async function getHandler( - type: NodeTypeIdentifier, - context: NodeHandlerContext -): Promise { - const handlers = handlersFromKits(context.kits ?? []); - const kitHandler = handlers[type]; - if (kitHandler) { - return kitHandler; - } - const graphHandler = await getGraphHandler(type, context); - if (graphHandler) { - return graphHandler; - } - throw new Error(`No handler for node type "${type}"`); -} - -/** - * A utility function to filter out empty (null or undefined) values from - * an object. - * - * @param obj -- The object to filter. - * @returns -- The object with empty values removed. - */ -function filterEmptyValues>(obj: T): T { - return Object.fromEntries( - Object.entries(obj).filter(([, value]) => !!value) - ) as T; -} - -type GraphHandlerThrottler = Throttler< - [NodeTypeIdentifier, NodeHandlerContext], - NodeHandlerObject | undefined ->; - -type NodeDescriberThrottler = Throttler< - [InputValues | undefined, GraphDescriptor, NodeDescriberContext], - NodeDescriberResult ->; - -const HANDLER_THROTTLE_DELAY = 10000; -const DESCRIBE_THROTTLE_DELAY = 5000; - -const GRAPH_HANDLER_CACHE = new Map< - NodeTypeIdentifier, - GraphHandlerThrottler ->(); - -type DescribeThrottlerWithHash = { - throttler: NodeDescriberThrottler; - hash: number; -}; - -const DESCRIBE_RESULT_CACHE = new Map< - NodeTypeIdentifier, - DescribeThrottlerWithHash ->(); - -export async function getGraphHandler( - type: NodeTypeIdentifier, - context: NodeHandlerContext -): Promise { - let throttler; - if (!GRAPH_HANDLER_CACHE.has(type)) { - throttler = new Throttler(getGraphHandlerInternal, HANDLER_THROTTLE_DELAY); - GRAPH_HANDLER_CACHE.set(type, throttler); - } else { - throttler = GRAPH_HANDLER_CACHE.get(type)!; - } - return throttler.call({}, type, context); -} - -async function getGraphHandlerInternal( - type: NodeTypeIdentifier, - context: NodeHandlerContext -): Promise { - const { base = SENTINEL_BASE_URL } = context; - const nodeTypeUrl = graphUrlLike(type) ? new URL(type, base) : undefined; - if (!nodeTypeUrl) { - return undefined; - } - const { loader } = context; - if (!loader) { - throw new Error(`Cannot load graph for type "${type}" without a loader.`); - } - const graph = await loader.load(type, context); - if (!graph) { - throw new Error(`Cannot load graph for type "${type}"`); - } - return { - invoke: async (inputs, context) => { - const base = context.board?.url && new URL(context.board?.url); - const invocationContext = base - ? { - ...context, - base, - } - : { ...context }; - - return await invokeGraph(graph, inputs, invocationContext); - }, - describe: async (inputs, _inputSchema, _outputSchema, context) => { - if (!context) { - return { inputSchema: {}, outputSchema: {} }; - } - const inputsHash = hash(inputs); - let describeThrottler = DESCRIBE_RESULT_CACHE.get(type); - if (!describeThrottler || describeThrottler.hash !== inputsHash) { - describeThrottler = { - throttler: new Throttler(describeGraph, DESCRIBE_THROTTLE_DELAY), - hash: inputsHash, - }; - - DESCRIBE_RESULT_CACHE.set(type, describeThrottler); - } - return describeThrottler.throttler.call({}, inputs, graph, context); - }, - metadata: filterEmptyValues({ - title: graph.title, - description: graph.description, - url: graph.url, - icon: graph.metadata?.icon, - help: graph.metadata?.help, - }), - } as NodeHandlerObject; -} - -async function describeGraph( - inputs: InputValues | undefined, - graph: GraphDescriptor, - context: NodeDescriberContext -) { - const inspectableGraph = inspect(graph, context); - const result = await inspectableGraph.describe(inputs); - return result; -} diff --git a/packages/breadboard/src/harness/error.ts b/packages/breadboard/src/harness/error.ts deleted file mode 100644 index 61c33fe7062..00000000000 --- a/packages/breadboard/src/harness/error.ts +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { ErrorObject } from "../types.js"; - -export const extractError = (e: unknown) => { - const error = e as Error; - let message; - if (error?.cause) { - const { cause } = error as { cause: ErrorObject }; - message = cause; - } else { - message = { error }; - } - return message; -}; - -export const formatRunError = (e: unknown) => { - if (typeof e === "string") { - return e; - } - if (e instanceof Error) { - return e.message; - } - if ("message" in (e as { message: string })) { - return (e as { message: string }).message; - } - // Presume it's an ErrorObject. - const error = (e as { error: unknown }).error; - if (typeof error === "string") { - return error; - } - if (error instanceof Error) { - return error.message; - } - return JSON.stringify(error); -}; diff --git a/packages/breadboard/src/harness/events.ts b/packages/breadboard/src/harness/events.ts deleted file mode 100644 index 8870eeeebe9..00000000000 --- a/packages/breadboard/src/harness/events.ts +++ /dev/null @@ -1,201 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - EdgeResponse, - ErrorResponse, - GraphEndProbeData, - GraphStartProbeData, - InputResponse, - InputValues, - NodeEndResponse, - NodeStartResponse, - OutputResponse, - SkipProbeMessage, -} from "../types.js"; -import { - HarnessRunResult, - RunEdgeEvent, - RunEndEvent, - RunErrorEvent, - RunGraphEndEvent, - RunGraphStartEvent, - RunInputEvent, - RunLifecycleEvent, - RunNextEvent, - RunNodeEndEvent, - RunNodeStartEvent, - RunOutputEvent, - RunSecretEvent, - RunSkipEvent, -} from "./types.js"; -import { SecretResult } from "./types.js"; -import { End } from "../remote/types.js"; - -const opts = { - composed: true, - bubbles: false, - cancelable: true, -}; - -export class PendingEvent extends Event { - static readonly eventName = "pending"; - - constructor(public data: { timestamp: number }) { - super(PendingEvent.eventName, { ...opts }); - } -} - -export class InputEvent extends Event implements RunInputEvent { - static readonly eventName = "input"; - - constructor( - public readonly running: boolean, - public data: InputResponse - ) { - super(InputEvent.eventName, { ...opts }); - } -} - -export class OutputEvent extends Event implements RunOutputEvent { - static readonly eventName = "output"; - readonly running = true; - - constructor(public data: OutputResponse) { - super(OutputEvent.eventName, { ...opts }); - } -} - -export class SecretEvent extends Event implements RunSecretEvent { - static readonly eventName = "secret"; - - constructor( - public readonly running: boolean, - public data: SecretResult["data"] - ) { - super(SecretEvent.eventName, { ...opts }); - } -} - -export class RunnerErrorEvent extends Event implements RunErrorEvent { - static readonly eventName = "error"; - readonly running = false; - - constructor(public data: ErrorResponse) { - super(RunnerErrorEvent.eventName, { ...opts }); - } -} - -export class EndEvent extends Event implements RunEndEvent { - static readonly eventName = "end"; - readonly running = false; - - constructor(public data: End) { - super(EndEvent.eventName, { ...opts }); - } -} - -export class SkipEvent extends Event implements RunSkipEvent { - static readonly eventName = "skip"; - readonly running = true; - - constructor(public data: SkipProbeMessage["data"]) { - super(SkipEvent.eventName, { ...opts }); - } -} - -export class EdgeEvent extends Event implements RunEdgeEvent { - static readonly eventName = "edge"; - readonly running = true; - - constructor(public data: EdgeResponse) { - super(EdgeEvent.eventName, { ...opts }); - } -} - -export class GraphStartEvent extends Event implements RunGraphStartEvent { - static readonly eventName = "graphstart"; - readonly running = true; - - constructor(public data: GraphStartProbeData) { - super(GraphStartEvent.eventName, { ...opts }); - } -} - -export class GraphEndEvent extends Event implements RunGraphEndEvent { - static readonly eventName = "graphend"; - readonly running = true; - - constructor(public data: GraphEndProbeData) { - super(GraphEndEvent.eventName, { ...opts }); - } -} - -export class NodeStartEvent extends Event implements RunNodeStartEvent { - static readonly eventName = "nodestart"; - readonly running = true; - - constructor(public data: NodeStartResponse) { - super(NodeStartEvent.eventName, { ...opts }); - } -} - -export class NodeEndEvent extends Event implements RunNodeEndEvent { - static readonly eventName = "nodeend"; - readonly running = true; - - constructor(public data: NodeEndResponse) { - super(NodeEndEvent.eventName, { ...opts }); - } -} - -export class PauseEvent extends Event implements RunLifecycleEvent { - static readonly eventName = "pause"; - - constructor( - public running: boolean, - public data: { timestamp: number } - ) { - super(PauseEvent.eventName, { ...opts }); - } -} - -export class ResumeEvent extends Event implements RunLifecycleEvent { - static readonly eventName = "resume"; - readonly running = true; - - constructor(public data: { timestamp: number; inputs?: InputValues }) { - super(ResumeEvent.eventName, { ...opts }); - } -} - -export class StartEvent extends Event implements RunLifecycleEvent { - static readonly eventName = "start"; - readonly running = true; - - constructor(public data: { timestamp: number; inputs?: InputValues }) { - super(StartEvent.eventName, { ...opts }); - } -} - -export class StopEvent extends Event implements RunLifecycleEvent { - static readonly eventName = "stop"; - - constructor( - public running: boolean, - public data: { timestamp: number } - ) { - super(StopEvent.eventName, { ...opts }); - } -} - -export class NextEvent extends Event implements RunNextEvent { - static readonly eventName = "next"; - - constructor(public data: HarnessRunResult | void) { - super(NextEvent.eventName, { ...opts }); - } -} diff --git a/packages/breadboard/src/harness/index.ts b/packages/breadboard/src/harness/index.ts deleted file mode 100644 index 855163c23e6..00000000000 --- a/packages/breadboard/src/harness/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { LocalRunner } from "./local-runner.js"; -import { RemoteRunner } from "./remote-runner.js"; -import { HarnessRunner, RunConfig } from "./types.js"; - -export type * from "./types.js"; - -export { serve, defineServeConfig } from "./serve.js"; -export { run } from "./run.js"; - -export type * from "./serve.js"; -export { type KitConfig } from "./kits.js"; - -export { createWorker } from "./worker.js"; -export { createSecretAskingKit } from "./secrets.js"; - -export const createRunner = (config: RunConfig): HarnessRunner => { - if (config.remote) { - return new RemoteRunner(config); - } - return new LocalRunner(config); -}; diff --git a/packages/breadboard/src/harness/kits.ts b/packages/breadboard/src/harness/kits.ts deleted file mode 100644 index 58bd765f929..00000000000 --- a/packages/breadboard/src/harness/kits.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { ProxyClient } from "../remote/proxy.js"; -import { Kit } from "../types.js"; -import { TransportFactory } from "./types.js"; - -/** - * The configuration for a proxy kit. - */ -export type ProxyKitConfig = { - /** - * The list of nodes to proxy. - */ - proxy: string[] | undefined; - location: string; - transport: "worker" | "http"; -}; - -export type KitConfig = Kit | ProxyKitConfig; - -const isProxyKitConfig = ( - kitOrConfig: KitConfig -): kitOrConfig is ProxyKitConfig => { - return "proxy" in kitOrConfig; -}; - -export const configureKits = (kits: KitConfig[], factory: TransportFactory) => { - return kits.map((kit) => { - if (isProxyKitConfig(kit)) { - const proxyClient = new ProxyClient(factory.client("proxy")); - return proxyClient.createProxyKit(kit.proxy); - } - return kit; - }); -}; diff --git a/packages/breadboard/src/harness/local-runner.ts b/packages/breadboard/src/harness/local-runner.ts deleted file mode 100644 index 96276db02bc..00000000000 --- a/packages/breadboard/src/harness/local-runner.ts +++ /dev/null @@ -1,223 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - HarnessRunner, - HarnessRunResult, - RunConfig, - RunEventTarget, -} from "./types.js"; -import { run } from "./run.js"; -import { InputValues, Schema } from "../types.js"; -import { - EndEvent, - InputEvent, - GraphEndEvent, - GraphStartEvent, - NodeEndEvent, - NodeStartEvent, - OutputEvent, - RunnerErrorEvent, - SecretEvent, - SkipEvent, - PauseEvent, - ResumeEvent, - StartEvent, - EdgeEvent, - NextEvent, -} from "./events.js"; -import { InspectableRunObserver } from "../inspector/types.js"; -import { timestamp } from "../timestamp.js"; - -export class LocalRunner - extends (EventTarget as RunEventTarget) - implements HarnessRunner -{ - #config: RunConfig; - #observers: InspectableRunObserver[] = []; - #run: ReturnType | null = null; - #pendingResult: HarnessRunResult | null = null; - #inRun = false; - #resumeWith: InputValues | undefined; - - /** - * Initialize the runner. - * This does not start the runner. - * - * @param config -- configuration for the run - */ - constructor(config: RunConfig) { - super(); - this.#config = config; - } - - addObserver(observer: InspectableRunObserver): void { - this.#observers.push(observer); - } - - async #notifyObservers(result: HarnessRunResult) { - for (const observer of this.#observers) { - try { - await observer.observe(result); - } catch (e) { - console.error("Observer failed to observe result", result, e); - } - } - } - - secretKeys(): string[] | null { - if (!this.#pendingResult || this.#pendingResult.type !== "secret") { - return null; - } - return this.#pendingResult.data.keys; - } - - inputSchema(): Schema | null { - if (!this.#pendingResult || this.#pendingResult.type !== "input") { - return null; - } - return this.#pendingResult.data.inputArguments.schema || null; - } - - running() { - return !!this.#run && !this.#pendingResult; - } - - async run(inputs?: InputValues): Promise { - if (this.#inRun) { - this.#resumeWith = inputs; - return false; - } - this.#inRun = true; - try { - const eventArgs = { - inputs, - timestamp: timestamp(), - }; - const starting = !this.#run; - - if (!this.#run) { - this.#run = run(this.#config); - } else if (this.#pendingResult) { - this.#pendingResult.reply({ inputs: inputs ?? {} }); - inputs = undefined; - } - this.#pendingResult = null; - - this.dispatchEvent( - starting ? new StartEvent(eventArgs) : new ResumeEvent(eventArgs) - ); - - for (;;) { - console.assert( - this.#run, - "Expected run to exist. If not, we might be having a re-entrant run." - ); - const result = await this.#run.next(); - this.dispatchEvent(new NextEvent(result.value)); - if (result.done) { - this.#run = null; - this.#pendingResult = null; - return true; - } - await this.#notifyObservers(result.value); - const { type, data, reply } = result.value; - switch (type) { - case "input": { - if (inputs) { - // When there are inputs to consume, consume them and - // continue the run. - this.dispatchEvent(new InputEvent(true, data)); - reply({ inputs }); - inputs = undefined; - } else { - // When there are no inputs to consume, pause the run - // and wait for the next input. - this.#pendingResult = result.value; - this.dispatchEvent(new InputEvent(false, data)); - if (this.#resumeWith) { - reply({ inputs: this.#resumeWith }); - this.#resumeWith = undefined; - } else { - this.dispatchEvent( - new PauseEvent(false, { - timestamp: timestamp(), - }) - ); - return false; - } - } - break; - } - case "error": { - this.dispatchEvent(new RunnerErrorEvent(data)); - break; - } - case "end": { - this.dispatchEvent(new EndEvent(data)); - break; - } - case "skip": { - this.dispatchEvent(new SkipEvent(data)); - break; - } - case "edge": { - this.dispatchEvent(new EdgeEvent(data)); - break; - } - case "graphstart": { - this.dispatchEvent(new GraphStartEvent(data)); - break; - } - case "graphend": { - this.dispatchEvent(new GraphEndEvent(data)); - break; - } - case "nodestart": { - this.dispatchEvent(new NodeStartEvent(data)); - break; - } - case "nodeend": { - this.dispatchEvent(new NodeEndEvent(data)); - break; - } - case "output": { - this.dispatchEvent(new OutputEvent(data)); - break; - } - case "secret": { - if (inputs) { - // When there are inputs to consume, consume them and - // continue the run. - this.dispatchEvent(new SecretEvent(true, data)); - reply({ inputs }); - inputs = undefined; - } else { - // When there are no inputs to consume, pause the run - // and wait for the next input. - this.#pendingResult = result.value; - this.dispatchEvent(new SecretEvent(false, data)); - if (this.#resumeWith) { - reply({ inputs: this.#resumeWith }); - this.#resumeWith = undefined; - } else { - this.dispatchEvent( - new PauseEvent(false, { - timestamp: timestamp(), - }) - ); - return false; - } - } - break; - } - } - } - } finally { - this.#inRun = false; - } - } -} diff --git a/packages/breadboard/src/harness/local.ts b/packages/breadboard/src/harness/local.ts deleted file mode 100644 index 6da73f135ea..00000000000 --- a/packages/breadboard/src/harness/local.ts +++ /dev/null @@ -1,182 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createDefaultDataStore } from "../data/index.js"; -import { asyncGen, runGraph } from "../index.js"; -import { createLoader } from "../loader/index.js"; -import { LastNode } from "../remote/types.js"; -import type { RunStackEntry } from "../run/types.js"; -import { saveRunnerState } from "../serialization.js"; -import { timestamp } from "../timestamp.js"; -import { - BreadboardRunResult, - ErrorObject, - GraphDescriptor, - Kit, - ProbeMessage, -} from "../types.js"; -import { Diagnostics } from "./diagnostics.js"; -import { extractError } from "./error.js"; -import { HarnessRunResult, RunConfig } from "./types.js"; -import { baseURL } from "./url.js"; - -const fromProbe = (probe: Probe) => { - const loadStateIfAny = () => { - if (probe.type === "nodestart") { - return probe.state; - } - return undefined; - }; - const state = loadStateIfAny(); - const data = structuredClone(probe.data); - return { - type: probe.type, - data, - state, - reply: async () => { - // Do nothing - }, - } as HarnessRunResult; -}; - -const fromRunnerResult = ( - result: Result -) => { - const { type, node, timestamp, invocationId } = result; - const bubbled = invocationId == -1; - - const saveState = async (): Promise => { - const runState = result.runState; - if (runState) { - return runState; - } - return [ - { - url: undefined, - path: [invocationId], - state: saveRunnerState(type, result.state), - }, - ]; - }; - - if (type === "input") { - const { inputArguments, path } = result; - return { - type, - data: { node, inputArguments, path, bubbled, timestamp }, - reply: async (value) => { - result.inputs = value.inputs; - }, - saveState, - } as HarnessRunResult; - } else if (type === "output") { - const { outputs, path } = result; - return { - type, - data: { node, outputs, path, timestamp, bubbled }, - reply: async () => { - // Do nothing - }, - saveState, - } as HarnessRunResult; - } - throw new Error(`Unknown result type "${type}".`); -}; - -const endResult = (last: LastNode | undefined) => { - return { - type: "end", - data: { timestamp: timestamp(), last }, - reply: async () => { - // Do nothing - }, - } as HarnessRunResult; -}; - -const errorResult = (error: string | ErrorObject) => { - return { - type: "error", - data: { error, timestamp: timestamp() }, - reply: async () => { - // Do nothing - }, - } as HarnessRunResult; -}; - -const maybeSaveProbe = ( - result: ProbeMessage, - last?: LastNode -): LastNode | undefined => { - const { type, data } = result; - if (type === "skip") { - return { - node: data.node, - missing: data.missingInputs, - }; - } - return last; -}; - -const maybeSaveResult = (result: BreadboardRunResult, last?: LastNode) => { - const { type, node } = result; - if (type === "output" || type === "input") { - return { - node, - missing: [], - }; - } - return last; -}; - -const load = async (config: RunConfig): Promise => { - const base = baseURL(config); - const loader = config.loader || createLoader(); - const graph = await loader.load(config.url, { base }); - if (!graph) { - throw new Error(`Unable to load graph from "${config.url}"`); - } - return graph; -}; - -export async function* runLocally(config: RunConfig, kits: Kit[]) { - yield* asyncGen(async (next) => { - const runner = config.runner || (await load(config)); - const loader = config.loader || createLoader(); - const store = config.store || createDefaultDataStore(); - const { base, signal, inputs, state, start } = config; - - try { - let last: LastNode | undefined; - - const probe = config.diagnostics - ? new Diagnostics(async (message) => { - last = maybeSaveProbe(message, last); - await next(fromProbe(message)); - }) - : undefined; - - for await (const data of runGraph(runner, { - probe, - kits, - loader, - store, - base, - signal, - inputs, - state, - start, - })) { - last = maybeSaveResult(data, last); - await next(fromRunnerResult(data)); - } - await next(endResult(last)); - } catch (e) { - const error = extractError(e); - console.error("Local Run error:", error); - await next(errorResult(error)); - } - }); -} diff --git a/packages/breadboard/src/harness/remote-runner.ts b/packages/breadboard/src/harness/remote-runner.ts deleted file mode 100644 index 295c62bbb40..00000000000 --- a/packages/breadboard/src/harness/remote-runner.ts +++ /dev/null @@ -1,352 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { InspectableRunObserver } from "../inspector/types.js"; -import { Schema, InputValues, GraphDescriptor } from "../types.js"; -import type { - HarnessRunner, - HarnessRunResult, - RunDiagnosticsLevel, - RunEventTarget, - SecretResult, -} from "./types.js"; -import { serverStreamEventDecoder } from "../remote/http.js"; -import type { - AsRemoteMessage, - InputRemoteMessage, - RemoteMessage, - RemoteRunConfig, -} from "../remote/types.js"; -import { - EndEvent, - InputEvent, - GraphEndEvent, - GraphStartEvent, - NodeEndEvent, - NodeStartEvent, - OutputEvent, - RunnerErrorEvent, - SkipEvent, - PauseEvent, - ResumeEvent, - StartEvent, - EdgeEvent, -} from "./events.js"; -import { timestamp } from "../timestamp.js"; -import { chunkRepairTransform } from "../remote/chunk-repair.js"; - -export type SecretRemoteMessage = AsRemoteMessage; - -export type HarnessRemoteMessage = RemoteMessage | SecretRemoteMessage; - -export type MessageConsumer = (message: HarnessRemoteMessage) => Promise; - -export type FetchType = typeof globalThis.fetch; - -export const remoteMessageTransform = () => { - return new TransformStream({ - transform(chunk, controller) { - try { - const message = JSON.parse(chunk) as HarnessRemoteMessage; - controller.enqueue(message); - } catch (e) { - throw new Error( - `Error transforming remote message: ${e}, message: ${chunk}` - ); - } - }, - }); -}; - -export const emptyGraph = () => ({}) as GraphDescriptor; - -export class HttpClient { - #url: string; - /** - * The API key for the remote service. - */ - #key: string; - #diagnostics: RunDiagnosticsLevel; - #fetch: FetchType | undefined; - #writer: MessageConsumer; - #fetching = false; - #lastMessage: InputRemoteMessage | null = null; - #signal: AbortSignal | null = null; - - constructor( - url: string, - key: string, - diagnostics: RunDiagnosticsLevel, - writer: MessageConsumer, - signal: AbortSignal | null, - fetch?: FetchType - ) { - this.#url = url; - this.#key = key; - this.#diagnostics = diagnostics; - this.#writer = writer; - this.#signal = signal; - this.#fetch = fetch; - } - - async #sendError(message: string) { - await this.#writer([ - "graphstart", - { - path: [], - timestamp: timestamp(), - graph: emptyGraph(), - }, - ]); - - await this.#writer(["error", { error: message, timestamp: timestamp() }]); - - await this.#writer([ - "graphend", - { - path: [], - timestamp: timestamp(), - }, - ]); - } - - #createBody(inputs: InputValues): string { - const body: InputValues = { - ...inputs, - $key: this.#key, - }; - if (this.#lastMessage) { - const [, , next] = this.#lastMessage; - if (next) { - body.$next = next; - } - } - if (this.#diagnostics) { - body.$diagnostics = this.#diagnostics; - } - return JSON.stringify(body); - } - - fetching(): boolean { - return this.#fetching; - } - - lastMessage(): HarnessRemoteMessage | null { - return this.#lastMessage; - } - - async send(inputs: InputValues): Promise { - if (this.#fetching) { - throw new Error("Fetch is already in progress."); - } - this.#fetching = true; - const response = await (this.#fetch ? this.#fetch : fetch)(this.#url, { - method: "POST", - body: this.#createBody(inputs), - }); - this.#lastMessage = null; - - if (!response.ok) { - await this.#sendError(`HTTP error: ${response.status}`); - } - - await response.body - ?.pipeThrough(new TextDecoderStream()) - .pipeThrough(chunkRepairTransform()) - .pipeThrough(serverStreamEventDecoder()) - .pipeThrough(remoteMessageTransform()) - .pipeTo( - new WritableStream({ - write: async (message) => { - this.#signal?.throwIfAborted(); - console.log( - "%cServer-Sent Event", - "background: #009; color: #FFF", - message - ); - const [type] = message; - if (type === "input") { - this.#lastMessage = message; - } - await this.#writer(message); - }, - close: async () => { - if (!this.#lastMessage && !this.#diagnostics) { - await this.#writer(["end", { timestamp: timestamp() }]); - } - }, - }) - ); - - this.#fetching = false; - return this.#lastMessage === null; - } -} - -export class RemoteRunner - extends (EventTarget as RunEventTarget) - implements HarnessRunner -{ - #config: RemoteRunConfig; - #client: HttpClient | null = null; - #observers: InspectableRunObserver[] = []; - #abortSignal: AbortSignal | null = null; - #fetch: FetchType; - #error = false; - - constructor(config: RemoteRunConfig, fetch?: FetchType) { - super(); - this.#config = config; - this.#fetch = fetch || globalThis.fetch; - this.#abortSignal = config.signal || null; - } - - addObserver(observer: InspectableRunObserver): void { - this.#observers.push(observer); - } - - async #notifyObservers(result: HarnessRunResult) { - for (const observer of this.#observers) { - try { - await observer.observe(result); - } catch (e) { - console.error("Observer failed to observe result", result, e); - } - } - } - - running(): boolean { - return this.#client?.fetching() || false; - } - - secretKeys(): string[] | null { - console.warn("Secret keys are not sent over to the client."); - return null; - } - - inputSchema(): Schema | null { - if (this.#client?.fetching()) { - return null; - } - const message = this.#client?.lastMessage(); - if (!message || message[0] !== "input") { - return null; - } - return message[1].inputArguments.schema || null; - } - - #initializeClient() { - const remote = this.#config.remote; - if (!remote) { - throw new Error("Remote configuration isn't specified."); - } - if (remote.type !== "http") { - throw new Error(`This runner only supports "http" remote configuration`); - } - const url = remote.url; - if (!url) { - throw new Error("Remote URL isn't specified."); - } - this.#client = new HttpClient( - url, - remote.key!, - this.#config.diagnostics || false, - async (message) => { - await this.#processMessage(message); - }, - this.#abortSignal, - this.#fetch - ); - } - - async #processMessage(message: HarnessRemoteMessage) { - const [type, data, next] = message; - await this.#notifyObservers({ - type, - data, - async reply() {}, - } as HarnessRunResult); - switch (type) { - case "input": { - const haveInputs = !next; - this.dispatchEvent(new InputEvent(haveInputs, data)); - if (!haveInputs) { - // When there are no inputs to consume, pause the run - // and wait for the next input. - this.dispatchEvent( - new PauseEvent(false, { - timestamp: timestamp(), - }) - ); - } - break; - } - case "error": { - this.dispatchEvent(new RunnerErrorEvent(data)); - this.#error = true; - break; - } - case "end": { - this.dispatchEvent(new EndEvent(data)); - this.#client = null; - break; - } - case "skip": { - this.dispatchEvent(new SkipEvent(data)); - break; - } - case "edge": { - this.dispatchEvent(new EdgeEvent(data)); - break; - } - case "graphstart": { - this.dispatchEvent(new GraphStartEvent(data)); - break; - } - case "graphend": { - this.dispatchEvent(new GraphEndEvent(data)); - break; - } - case "nodestart": { - this.dispatchEvent(new NodeStartEvent(data)); - break; - } - case "nodeend": { - this.dispatchEvent(new NodeEndEvent(data)); - break; - } - case "output": { - this.dispatchEvent(new OutputEvent(data)); - break; - } - } - } - - async run(inputs?: InputValues): Promise { - if (this.#error) { - return true; - } - if (this.#abortSignal?.aborted) { - this.#error = true; - return true; - } - - const starting = !this.#client; - if (!this.#client) { - this.#initializeClient(); - } - - const eventArgs = { - inputs, - timestamp: timestamp(), - }; - - this.dispatchEvent( - starting ? new StartEvent(eventArgs) : new ResumeEvent(eventArgs) - ); - - return this.#client!.send(inputs || {}); - } -} diff --git a/packages/breadboard/src/harness/run.ts b/packages/breadboard/src/harness/run.ts deleted file mode 100644 index 0744fd5128a..00000000000 --- a/packages/breadboard/src/harness/run.ts +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Kit, asyncGen } from "../index.js"; -import { HTTPClientTransport } from "../remote/http.js"; -import { ProxyClient } from "../remote/proxy.js"; -import { runLocally } from "./local.js"; -import { configureSecretAsking } from "./secrets.js"; -import { HarnessRunResult, RunConfig } from "./types.js"; -import { runInWorker } from "./worker.js"; - -const configureKits = async (config: RunConfig): Promise => { - // If a proxy is configured, add the proxy kit to the list of kits. - if (!config.proxy) return config.kits; - const kits: Kit[] = []; - for (const proxyConfig of config.proxy) { - if (typeof proxyConfig === "function") { - const config = await proxyConfig(); - if (!config) continue; - kits.push(await proxyConfig()); - } else { - switch (proxyConfig.location) { - case "http": { - if (!proxyConfig.url) { - throw new Error("No node proxy server URL provided."); - } - const proxyClient = new ProxyClient( - new HTTPClientTransport(proxyConfig.url) - ); - kits.push(proxyClient.createProxyKit(proxyConfig.nodes)); - break; - } - default: { - throw new Error( - "Only HTTP node proxy server is supported at this time." - ); - } - } - } - } - return [...kits, ...config.kits]; -}; - -export async function* run(config: RunConfig) { - if (!config.remote) { - yield* asyncGen(async (next) => { - const kits = configureSecretAsking( - config.interactiveSecrets, - await configureKits(config), - next - ); - - for await (const data of runLocally(config, kits)) { - await next(data); - } - }); - } else if (config.remote.type === "worker") { - const workerURL = config.remote && config.remote.url; - if (!workerURL) { - throw new Error("Worker harness requires a worker URL"); - } - yield* runInWorker(workerURL, config); - } else { - throw new Error( - `Unsupported harness configuration: ${JSON.stringify(config, null, 2)}` - ); - } -} diff --git a/packages/breadboard/src/harness/secrets.ts b/packages/breadboard/src/harness/secrets.ts deleted file mode 100644 index e7a37d0d78c..00000000000 --- a/packages/breadboard/src/harness/secrets.ts +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { HarnessRunResult, RunConfig, SecretResult } from "./types.js"; -import { KitBuilder } from "../kits/builder.js"; -import { timestamp } from "../timestamp.js"; -import { asRuntimeKit, callHandler } from "../index.js"; -import type { - InputValues, - Kit, - NodeHandler, - NodeTypeIdentifier, - OutputValues, -} from "../types.js"; -import type { ClientRunResult } from "../remote/types.js"; - -/** - * Get all secret handlers from the given kits. - * This is used to create a fallback list for secret asking. - */ -const secretHandlersFromKits = (kits: Kit[]): NodeHandler[] => { - const secretHandlers = []; - for (const kit of kits) { - for (const [key, handler] of Object.entries(kit.handlers)) { - if (key === "secrets") { - secretHandlers.push(handler); - } - } - } - return secretHandlers; -}; - -export const configureSecretAsking = ( - interactiveSecrets: RunConfig["interactiveSecrets"], - existingKits: Kit[], - next: (data: HarnessRunResult) => Promise -): Kit[] => { - if (interactiveSecrets === true) { - return [createSecretAskingKit(next), ...existingKits]; - } else if (interactiveSecrets === "fallback") { - return [ - createSecretAskingKit(next, secretHandlersFromKits(existingKits)), - ...existingKits, - ]; - } else { - return existingKits; - } -}; - -const interactiveSecretsHandler = ( - next: (result: ClientRunResult) => Promise -) => { - return async (inputs: InputValues) => { - const { keys } = inputs as { keys: string[] }; - if (!keys) return {}; - let outputs = {}; - await next({ - type: "secret", - data: { keys, timestamp: timestamp() }, - reply: async (value) => { - outputs = value.inputs; - }, - }); - return outputs as OutputValues; - }; -}; - -const fallbackHandler = ( - nodeType: NodeTypeIdentifier, - handlers: NodeHandler[] -) => { - const handler: NodeHandler = async (inputs, context) => { - for (const handler of handlers) { - const outputs = await callHandler(handler, inputs, context); - if (outputs && !outputs["$error"]) { - return outputs; - } - } - throw new Error(`No handler found for type "${nodeType}"`); - }; - return handler; -}; - -export const createSecretAskingKit = ( - next: (result: ClientRunResult) => Promise, - fallback?: NodeHandler[] -) => { - const interactive = interactiveSecretsHandler(next); - const secrets = fallback - ? fallbackHandler("secrets", [...fallback, interactive]) - : interactive; - const secretAskingKit = new KitBuilder({ - url: "secret-asking-kit", - }).build({ secrets }); - return asRuntimeKit(secretAskingKit); -}; diff --git a/packages/breadboard/src/harness/serve.ts b/packages/breadboard/src/harness/serve.ts deleted file mode 100644 index 4211a230adf..00000000000 --- a/packages/breadboard/src/harness/serve.ts +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createLoader } from "../loader/index.js"; -import { InitServer } from "../remote/init.js"; -import { RunServer } from "../remote/run.js"; -import { - PortDispatcher, - WorkerClientTransport, - WorkerServerTransport, -} from "../remote/worker.js"; -import { KitConfig, configureKits } from "./kits.js"; -import { TransportFactory } from "./types.js"; -import { baseURL } from "./url.js"; - -/** - * The Breadboard Serve configuration. - */ -export type ServeConfig = { - /** - * The transport to use. Currently, only "worker" is supported. - */ - transport: "worker"; - /** - * The URL of the board to load. If not specified, the server will ask the - * client for the URL. - */ - url?: string; - /** - * The base URL relative to which to load the board. - * If ran in a browser, defaults to the current URL. - * Otherwise, defaults to invoking module's URL. - */ - base?: URL; - /** - * The kits to use for serving breadboard. Accepts an array of kits or - * proxy configurations. - * If the kit is specified directly, it will be used as-is. - * If the kit is specified as a proxy configuration, a proxy kit will be - * created and and a proxy client will be started. - */ - kits: KitConfig[]; - /** - * Whether to enable diagnostics. Defaults to false. - * When diagnostics are enabled, the server will send graphstart/graphend and - * nodestart/nodeend messages to the client. - */ - diagnostics?: boolean; -}; - -const isInWorker = () => { - return ( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - typeof WorkerGlobalScope !== "undefined" && - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - self instanceof WorkerGlobalScope - ); -}; - -const maybeCreateWorker = () => { - throw new Error("Not implemented"); -}; - -class WorkerTransportFactory { - #dispatcher: PortDispatcher; - - constructor(dispatcher: PortDispatcher) { - this.#dispatcher = dispatcher; - } - - client(label: string) { - return new WorkerClientTransport( - this.#dispatcher.send(label) - ); - } - - server(label: string) { - return new WorkerServerTransport( - this.#dispatcher.receive(label) - ); - } -} - -const getBoardURL = async (config: ServeConfig, factory: TransportFactory) => { - const url = config.url; - if (url) return url; - - const initServer = new InitServer(factory.server("load")); - return await initServer.serve(); -}; - -/** - * Start the Breadboard run server. Currently, this function is somewhat - * specialized to the worker transport, but (one hopes) will eventually - * grow up to be more general and flexible. - * @param config - The configuration for the server or a promise that resolves - * to the configuration for the server. - * @returns - a promise that resolves when the server is done serving. - */ -export const serve = async (config: ServeConfig | Promise) => { - const inWorker = isInWorker(); - const worker = inWorker ? (self as unknown as Worker) : maybeCreateWorker(); - const factory = new WorkerTransportFactory(new PortDispatcher(worker)); - config = await config; - if (config.transport !== "worker") { - throw new Error("Only worker transport is supported at this time."); - } - const kits = configureKits(config.kits, factory); - // TODO: Figure out how to initialize. - const isRunServer = true; - if (!isRunServer) return; - - const server = new RunServer(factory.server("run")); - const url = await getBoardURL(config, factory); - const base = baseURL(config); - const loader = createLoader(); - const graph = await loader.load(url, { base }); - if (!graph) { - throw new Error(`Unable to load graph from "${config.url}"`); - } - return server.serve(graph, !!config.diagnostics, { kits }); -}; - -/** - * A helper function to define a serve configuration. Especially useful in - * TypeScript, where the type of the configuration is inferred from the - * argument. - * @param config - The configuration for the server. - * @returns - The configuration for the server. - */ -export const defineServeConfig = (config: ServeConfig) => { - return config; -}; diff --git a/packages/breadboard/src/harness/types.ts b/packages/breadboard/src/harness/types.ts deleted file mode 100644 index 475bd29a35f..00000000000 --- a/packages/breadboard/src/harness/types.ts +++ /dev/null @@ -1,359 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { StartLabel } from "@google-labs/breadboard-schema/graph.js"; -import type { DataStore } from "../data/types.js"; -import { InspectableRunObserver } from "../inspector/types.js"; -import type { GraphLoader } from "../loader/types.js"; -import type { NodeProxyConfig } from "../remote/config.js"; -import type { - AnyClientRunResult, - AnyProbeClientRunResult, - ClientRunResult, - ClientTransport, - End, - LoadResponse, - ServerTransport, -} from "../remote/types.js"; -import type { ManagedRunState } from "../run/types.js"; -import type { - GraphDescriptor, - ErrorResponse, - InputResponse, - InputValues, - Kit, - OutputResponse, - OutputValues, - SkipProbeMessage, - GraphStartProbeData, - GraphEndProbeData, - NodeEndResponse, - NodeStartResponse, - Schema, - EdgeResponse, -} from "../types.js"; -import { - TypedEventTargetType, - TypedEventTarget, -} from "../utils/typed-event-target.js"; - -/** - * The board has been loaded - */ -export type LoadResult = { - type: "load"; - data: LoadResponse; -}; - -/** - * The board is asking for input - */ -export type InputResult = { - type: "input"; - data: InputResponse; -}; - -/** - * The board is sending output - */ -export type OutputResult = { - type: "output"; - data: OutputResponse; -}; - -/** - * Sent when the harness is asking for secret - */ -export type SecretResult = { - type: "secret"; - data: SecretResponse; -}; - -export type SecretResponse = { - keys: string[]; - timestamp: number; -}; - -/** - * Sent when the board run process reports an error - */ -export type ErrorResult = { - type: "error"; - data: ErrorResponse; -}; - -/** - * Sent when the board run finished - */ -export type EndResult = { - type: "end"; - data: Record; -}; - -export type HarnessRunResult = - | AnyClientRunResult - | ClientRunResult; - -export type HarnessProbeResult = AnyProbeClientRunResult; - -export type SecretHandler = (keys: { - keys?: string[]; -}) => Promise; - -export type TransportFactory = { - client(label: string): ClientTransport; - server(label: string): ServerTransport; -}; - -export type ProxyLocation = "main" | "worker" | "http" | "python"; - -export type CustomProxyConfig = () => Promise; - -export type HarnessProxyConfig = - | { - location: ProxyLocation; - url?: string; - nodes: NodeProxyConfig; - } - | CustomProxyConfig; - -export type HarnessRemoteConfig = - | { - /** - * The type of the remote runtime. Can be "http" or "worker". - */ - type: "http" | "worker"; - /** - * The URL of the remote runtime. Specifies the URL of the worker - * script if `type` is "worker", or the URL of the runtime server if - * `type` is "http". - */ - url: string; - /** - * API Key - */ - key?: string; - } - | false; - -/** - * The level of diagnostics to supply during the run. - * If `true`, all probe events will be supplied. - * If `"top"`, only the top-level probe events will be supplied. - * If `false`, no probe events will be supplied. - * - * Defaults to `false`. - */ -export type RunDiagnosticsLevel = boolean | "top"; - -export type RunConfig = { - /** - * The URL of the board to run. - */ - url: string; - /** - * The base URL relative to which to load the board. - * If ran in a browser, defaults to the current URL. - * Otherwise, defaults to invoking module's URL. - */ - base?: URL; - /** - * The kits to use by the runtime. - */ - kits: Kit[]; - /** - * The loader to use when loading boards. - */ - loader?: GraphLoader; - /** - * Specifies the remote environment in which to run the harness. - * In this situation, the harness creates a runtime client, and relies - * on the remote environment to act as the runtime server - * If `remote` is not specified or is "false", this harness runs the board - * itself, acting as a server (there is no need for a client). - */ - remote?: HarnessRemoteConfig; - /** - * Specifies a list of node proxies to use. Each item specifies a proxy - * server and a list of nodes that will be proxied to it. - */ - proxy?: HarnessProxyConfig[]; - /** - * Specifies whether to output diagnostics information. - * Defaults to `false`. - */ - diagnostics?: RunDiagnosticsLevel; - /** - * Specifies a runner to use. This can be used instead of loading a board - * from a URL. - */ - runner?: GraphDescriptor; - /** - * The `AbortSignal` that can be used to stop the board run. - */ - signal?: AbortSignal; - /** - * The values that will be supplied to the bubbled inputs during a board run. - * This enables automatically providing some of the values like the model - * name without interrupting the run of the board. - */ - inputs?: InputValues; - /** - * Specifies whether or not secrets are asked for interactively. When `true`, - * the `secret` result will start showing up in the run results whenever - * the secret is asked for. Otherwise, the `secrets` node will try to find - * the secrets on its own. - * - * When set to `"fallback"`, the secrets will be asked for interactively - * only if the secrets node is not able to find the secrets on its own. - */ - interactiveSecrets?: boolean | "fallback"; - /** - * The data store to use for storing data. - */ - store?: DataStore; - /** - * The state from which to resume the run. - */ - state?: ManagedRunState; - /** - * Start label to use for the run. This is useful for specifying a particular - * node as the start of the run. If not provided, nodes without any incoming - * edges will be used. - */ - start?: StartLabel; -}; - -export type RunEventMap = { - start: RunLifecycleEvent; - pause: RunLifecycleEvent; - resume: RunLifecycleEvent; - next: RunNextEvent; - input: RunInputEvent; - output: RunOutputEvent; - secret: RunSecretEvent; - error: RunErrorEvent; - skip: RunSkipEvent; - edge: RunEdgeEvent; - graphstart: RunGraphStartEvent; - graphend: RunGraphEndEvent; - nodestart: RunNodeStartEvent; - nodeend: RunNodeEndEvent; - end: RunEndEvent; -}; - -export type RunLifecycleEvent = Event & { - running: boolean; - data: { timestamp: number; inputs?: InputValues }; -}; - -export type RunNextEvent = Event & { - data: HarnessRunResult | void; -}; - -export type RunInputEvent = Event & { - data: InputResponse; - running: boolean; -}; - -export type RunOutputEvent = Event & { - data: OutputResponse; - running: true; -}; - -export type RunSecretEvent = Event & { - data: SecretResult["data"]; - running: boolean; -}; - -export type RunErrorEvent = Event & { - data: ErrorResponse; - running: false; -}; - -export type RunEndEvent = Event & { - data: End; - running: false; -}; - -export type RunSkipEvent = Event & { - data: SkipProbeMessage["data"]; - running: true; -}; - -export type RunEdgeEvent = Event & { - data: EdgeResponse; - running: true; -}; - -export type RunGraphStartEvent = Event & { - data: GraphStartProbeData; - running: true; -}; - -export type RunGraphEndEvent = Event & { - data: GraphEndProbeData; - running: true; -}; - -export type RunNodeStartEvent = Event & { - data: NodeStartResponse; - running: true; -}; - -export type RunNodeEndEvent = Event & { - data: NodeEndResponse; - running: true; -}; - -export type RunEventTarget = TypedEventTarget; - -export type HarnessRunner = TypedEventTargetType & { - addObserver(observer: InspectableRunObserver): void; - - /** - * Check if the runner is running or not. - * - * @returns -- true if the runner is currently running, or false otherwise. - */ - running(): boolean; - - /** - * A convenience method to get the secret keys that the runner is - * waiting for. This information can also be obtained by listening to - * the `secret` event. - * - * Returns null if the runner is not waiting for any secrets. - * - * @returns -- set of secret keys that the runner is waiting for, or null. - */ - secretKeys(): string[] | null; - - /** - * A convenience method to get the input schema that the runner is - * waiting for. This information can also be obtained by listening to - * the `input` event. - * - * Returns null if the runner is not waiting for any inputs. - * - * @returns -- the input schema that the runner is waiting for, or null. - */ - inputSchema(): Schema | null; - - /** - * Starts or resumes the running of the board. - * If the runner is waiting for input, the input arguments will be used - * to provide the input values. - * - * If the runner is done, it will return true. If the runner is waiting - * for input or secret, it will return false. - * - * @param inputs -- input values to provide to the runner. - * @returns -- true if the runner is done, or false if it is waiting - * for input. - */ - run(inputs?: InputValues): Promise; -}; diff --git a/packages/breadboard/src/harness/url.ts b/packages/breadboard/src/harness/url.ts deleted file mode 100644 index 20ed90c1b03..00000000000 --- a/packages/breadboard/src/harness/url.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { SENTINEL_BASE_URL } from "../loader/index.js"; -import { ServeConfig } from "./serve.js"; -import { RunConfig } from "./types.js"; - -export const baseURL = (config: RunConfig | ServeConfig) => { - if (config.base) return config.base; - if ("window" in globalThis) return new URL(self.location.href); - return SENTINEL_BASE_URL; -}; diff --git a/packages/breadboard/src/harness/worker.ts b/packages/breadboard/src/harness/worker.ts deleted file mode 100644 index 0dcd63d3ca0..00000000000 --- a/packages/breadboard/src/harness/worker.ts +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { HarnessRunResult, RunConfig } from "./types.js"; -import { asyncGen } from "../index.js"; -import { createSecretAskingKit } from "./secrets.js"; -import { ProxyServer } from "../remote/proxy.js"; -import { - PortDispatcher, - WorkerClientTransport, - WorkerServerTransport, -} from "../remote/worker.js"; -import { RunClient } from "../remote/run.js"; -import { InitClient } from "../remote/init.js"; -import type { RunState } from "../run/types.js"; - -export const createWorker = (url: string) => { - const workerURL = new URL(url, location.href); - const code = `import "${workerURL}";`; - const blob = new Blob([code], { type: "text/javascript" }); - const blobUrl = URL.createObjectURL(blob); - return new Worker(blobUrl, { type: "module" }); -}; - -export async function* runInWorker( - workerURL: string, - config: RunConfig, - state?: RunState -) { - const worker = createWorker(workerURL); - const dispatcher = new PortDispatcher(worker); - const initClient = new InitClient( - new WorkerClientTransport(dispatcher.send("load")) - ); - const proxyServer = new ProxyServer( - new WorkerServerTransport(dispatcher.receive("proxy")) - ); - const runClient = new RunClient( - new WorkerClientTransport(dispatcher.send("run")) - ); - - await initClient.load(config.url); - - yield* asyncGen(async (next) => { - const kits = [createSecretAskingKit(next), ...config.kits]; - const proxyConfig = config.proxy?.[0]; - let proxy; - if (proxyConfig && typeof proxyConfig !== "function") { - proxy = proxyConfig.nodes; - } - proxyServer.serve({ kits, proxy }); - - for await (const data of runClient.run(state)) { - await next(data); - } - }); -} diff --git a/packages/breadboard/src/id.ts b/packages/breadboard/src/id.ts deleted file mode 100644 index 6e60e9365a8..00000000000 --- a/packages/breadboard/src/id.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export class IdVendor { - #map = new Map(); - - vendId(o: object, prefix: string) { - let count = this.#map.get(o) || 0; - count++; - this.#map.set(o, count); - return `${prefix}-${count}`; - } -} diff --git a/packages/breadboard/src/index.ts b/packages/breadboard/src/index.ts deleted file mode 100644 index 0d8a9c34ade..00000000000 --- a/packages/breadboard/src/index.ts +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export type * from "./types.js"; - -export { Board } from "./board.js"; -export { Node } from "./node.js"; -export { SchemaBuilder, combineSchemas } from "./schema.js"; -export { RunResult } from "./run.js"; -export { TraversalMachine } from "./traversal/machine.js"; -export { MachineResult } from "./traversal/result.js"; -export { traversalResultFromStack } from "./run/lifecycle.js"; -export { toMermaid } from "./mermaid.js"; -export { callHandler } from "./handler.js"; -export { asRuntimeKit } from "./kits/ctors.js"; -export { - StreamCapability, - isStreamCapability, - patchReadableStream, - streamFromAsyncGen, - clone, - type StreamCapabilityType, - type PatchedReadableStream, -} from "./stream.js"; - -// New Syntax: -export { - board, - // TODO Alias for easier migration to the new name. Remove in a future breaking change. - board as recipe, - code, -} from "./new/grammar/board.js"; -export { addKit } from "./new/grammar/kits.js"; -export { base } from "./new/grammar/base.js"; -export type { - NodeValue as NewNodeValue, - InputValues as NewInputValues, - OutputValues as NewOutputValues, - Serializeable, - AbstractNode, -} from "./new/runner/types.js"; -export type { - Lambda, - InputsForHandler, - InputsForGraphDeclaration, - OutputsForGraphDeclaration, - NodeFactory as NewNodeFactory, - NodeProxy as __NodeProxy, - InputsMaybeAsValues, - OutputsMaybeAsValues, - OutputValuesOrUnknown, - ProjectBackToOutputValues as __ProjectBackToOutputValues, - InputValues as NewInputValuesWithNodeFactory, - AbstractValue as V, -} from "./new/grammar/types.js"; -export { asyncGen } from "./utils/async-gen.js"; -export { Throttler } from "./utils/throttler.js"; -export { type SemVer, SemanticVersioning } from "./utils/semver.js"; -export type * from "./utils/typed-event-target.js"; - -/** - * Helpers for handling BreadboardCapability. - */ -export { getGraphDescriptor } from "./capability.js"; - -/** - * The Inspector API. - */ -export * from "./inspector/types.js"; -export { inspect, createRunObserver } from "./inspector/index.js"; -export { PortStatus } from "./inspector/types.js"; - -/** - * The Editor API. - */ -export type * from "./editor/types.js"; -export { editGraph as edit, blank, blankLLMContent } from "./editor/index.js"; - -/** - * The Loader API - */ -export type * from "./loader/types.js"; -export { createLoader } from "./loader/index.js"; - -export { formatGraphDescriptor } from "./formatter.js"; - -/** - * DataCapability helpers. - */ -export type * from "./data/types.js"; -export { - asBase64, - asBlob, - deflateData, - inflateData, - isDataCapability, - isInlineData, - isStoredData, - isSerializedData, - isFunctionCallCapabilityPart, - isFunctionResponseCapabilityPart, - isLLMContent, - isLLMContentArray, - isMetadataEntry, - isTextCapabilityPart, - toInlineDataPart, - toStoredDataPart, - createDefaultDataStore, - createDefaultRunStore, -} from "./data/index.js"; - -/** - * Managed Run State API - */ -export type * from "./run/types.js"; -export { createRunStateManager } from "./run/index.js"; -export { invokeGraph } from "./run/invoke-graph.js"; -export { runGraph } from "./run/run-graph.js"; diff --git a/packages/breadboard/src/inspector/bubbled-node.ts b/packages/breadboard/src/inspector/bubbled-node.ts deleted file mode 100644 index 0f265f01bd7..00000000000 --- a/packages/breadboard/src/inspector/bubbled-node.ts +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { EdgeType, describeInput } from "./schemas.js"; -import { collectPorts } from "./ports.js"; -import { filterBySchema } from "../schema.js"; -import { - InspectableEdge, - InspectableNode, - InspectableNodePorts, - InspectableNodeType, - InspectablePortList, -} from "./types.js"; -import { - InputValues, - NodeConfiguration, - NodeDescriberResult, - NodeDescriptor, - OutputValues, -} from "../types.js"; -import { - NodeMetadata, - StartLabel, -} from "@google-labs/breadboard-schema/graph.js"; - -/** - * This is a special kind of an `InspectableNode`, representing a bubbled - * node instance. Its key difference is that, when it's type = input, - * it will narrow down the ports and values to only the ones that bubbled up. - * For instance, the actual input node might have four parameters, but - * only one of them bubbled up. This node will make sure that it looks as if - * it only has that one parameter. - */ -export class BubbledInspectableNode implements InspectableNode { - descriptor: NodeDescriptor; - #actual: InspectableNode; - - constructor(actual: InspectableNode) { - const descriptor = actual.descriptor; - if (descriptor.type !== "input" && descriptor.type !== "output") { - throw new Error( - "BubbledInspectableNode can only be an input or an output" - ); - } - this.#actual = actual; - this.descriptor = descriptor; - } - - title(): string { - return this.#actual.title(); - } - - description(): string { - return this.#actual.description(); - } - - incoming(): InspectableEdge[] { - return this.#actual.incoming(); - } - - outgoing(): InspectableEdge[] { - return this.#actual.outgoing(); - } - - isEntry(label?: StartLabel): boolean { - return this.#actual.isEntry(label); - } - - startLabels(): StartLabel[] | undefined { - return this.#actual.startLabels(); - } - - isExit(): boolean { - return this.#actual.isExit(); - } - - type(): InspectableNodeType { - return this.#actual.type(); - } - - configuration(): NodeConfiguration { - return this.#actual.configuration(); - } - - metadata(): NodeMetadata { - return this.#actual.metadata(); - } - - async describe( - inputs?: InputValues | undefined - ): Promise { - if (this.descriptor.type === "input") { - return describeInput({ inputs }); - } - return this.#actual.describe(inputs); - } - - async ports( - inputValues?: InputValues | undefined, - outputValues?: OutputValues | undefined - ): Promise { - if (this.descriptor.type === "input") { - const described = describeInput({ inputs: inputValues }); - - const bubbledValues = filterBySchema( - outputValues || {}, - described.outputSchema - ); - const inputs: InspectablePortList = { - fixed: described.inputSchema.additionalProperties === false, - ports: collectPorts( - EdgeType.In, - this.incoming(), - described.inputSchema, - false, - true, - inputValues - ), - }; - const outputs: InspectablePortList = { - fixed: described.outputSchema.additionalProperties === false, - ports: collectPorts( - EdgeType.Out, - [], - described.outputSchema, - false, - false, - bubbledValues - ), - }; - return { inputs, outputs }; - } - return this.#actual.ports(inputValues, outputValues || undefined); - } -} diff --git a/packages/breadboard/src/inspector/edge.ts b/packages/breadboard/src/inspector/edge.ts deleted file mode 100644 index 4637688d159..00000000000 --- a/packages/breadboard/src/inspector/edge.ts +++ /dev/null @@ -1,178 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Edge as EdgeDescriptor, GraphDescriptor } from "../types.js"; -import { - InspectableEdge, - InspectableEdgeType, - InspectableNodeCache, - InspectablePort, - ValidateResult, -} from "./types.js"; - -/** - * This helper is necessary because both "*" and "" are valid representations - * of a wildcard edge tail. This function ensures that the edge is always - * consistent. - * @param edge -- the edge to fix up - * @returns - */ -export const fixUpStarEdge = (edge: EdgeDescriptor): EdgeDescriptor => { - if (edge.out === "*") { - return { ...edge, in: "" }; - } - return edge; -}; - -/** - * This is inverse of the helper above, necessary when working with - * instances of `InspectableEdge` directly, since they will show "*" on both - * sides of the edge. - * @param edge -- the edge to un-fix up - * @returns - */ -export const unfixUpStarEdge = (edge: EdgeDescriptor): EdgeDescriptor => { - if (edge.out === "*") { - return { ...edge, in: "*" }; - } - return edge; -}; - -export const fixupConstantEdge = (edge: EdgeDescriptor): EdgeDescriptor => { - const { constant, ...rest } = edge; - if (constant === false) { - return rest; - } - return edge; -}; - -class Edge implements InspectableEdge { - #nodes: InspectableNodeCache; - #edge: EdgeDescriptor; - - constructor(nodes: InspectableNodeCache, edge: EdgeDescriptor) { - this.#nodes = nodes; - this.#edge = edge; - } - - get from() { - const from = this.#nodes.get(this.#edge.from); - console.assert(from, "From node not found when getting from."); - return from!; - } - - get out() { - return this.#edge.out as string; - } - - get to() { - const to = this.#nodes.get(this.#edge.to); - console.assert(to, "To node not found when getting to."); - return to!; - } - - get in() { - const edgein = this.#edge.out === "*" ? "*" : this.#edge.in; - return edgein as string; - } - - get type() { - if (this.#edge.out === "*") return InspectableEdgeType.Star; - if (this.#edge.out === "") return InspectableEdgeType.Control; - if (this.#edge.constant) return InspectableEdgeType.Constant; - return InspectableEdgeType.Ordinary; - } - - async outPort(): Promise { - const ports = await this.from.ports(); - return ports.outputs.ports.find((port) => port.name === this.out)!; - } - - async inPort(): Promise { - const ports = await this.to.ports(); - return ports.inputs.ports.find((port) => port.name === this.in)!; - } - - async validate(): Promise { - const [outPort, inPort] = await Promise.all([ - this.outPort(), - this.inPort(), - ]); - if (outPort === undefined || inPort === undefined) { - return { status: "unknown" }; - } - const canConnectAnalysis = outPort.type.analyzeCanConnect(inPort.type); - if (!canConnectAnalysis.canConnect) { - return { - status: "invalid", - errors: canConnectAnalysis.details, - }; - } - return { status: "valid" }; - } -} - -export class EdgeCache { - #nodes: InspectableNodeCache; - #map: Map = new Map(); - - constructor(nodes: InspectableNodeCache) { - this.#nodes = nodes; - } - - populate(graph: GraphDescriptor) { - // Initialize the edge map from the graph. This is only done once, and all - // following updates are performed incrementally. - return (this.#map = new Map( - graph.edges.map((edge) => [edge, new Edge(this.#nodes, edge)]) - )); - } - - get(edge: EdgeDescriptor): InspectableEdge | undefined { - return this.#map.get(edge); - } - - getOrCreate(edge: EdgeDescriptor): InspectableEdge { - let result = this.get(edge); - if (result) { - return result; - } - result = new Edge(this.#nodes, edge); - this.add(edge); - return result; - } - - add(edge: EdgeDescriptor) { - console.assert(!this.#map.has(edge), "Edge already exists when adding."); - this.#map.set(edge, new Edge(this.#nodes, edge)); - } - - remove(edge: EdgeDescriptor) { - console.assert(this.#map.has(edge), "Edge not found when removing."); - this.#map.delete(edge); - } - - has(edge: EdgeDescriptor): boolean { - return this.#map.has(edge); - } - - hasByValue(edge: EdgeDescriptor): boolean { - edge = unfixUpStarEdge(edge); - const edges = this.edges(); - return !!edges.find((e) => { - return ( - e.from.descriptor.id === edge.from && - e.to.descriptor.id === edge.to && - e.out === edge.out && - e.in === edge.in - ); - }); - } - - edges(): InspectableEdge[] { - return Array.from(this.#map.values()); - } -} diff --git a/packages/breadboard/src/inspector/graph-store.ts b/packages/breadboard/src/inspector/graph-store.ts deleted file mode 100644 index 9e79b1a79b7..00000000000 --- a/packages/breadboard/src/inspector/graph-store.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "../types.js"; -import { GraphUUID, GraphDescriptorStore } from "./types.js"; - -const toUUID = (url: string, version: number): GraphUUID => { - return `${version}|${url}`; -}; - -export class GraphStore implements GraphDescriptorStore { - #entries = new Map(); - #ids = new Map(); - - #getOrSetGraphId(graph: GraphDescriptor, version: number): GraphUUID { - if (graph.url) { - return toUUID(graph.url, version); - } - // if there's no URL, fallback to stringifying the graph - // and making a blob URL. - // TODO: Remove the needs for this. All graphs must have a URL. - const key = JSON.stringify(graph); - if (this.#ids.has(key)) { - return this.#ids.get(key) as GraphUUID; - } - const id = toUUID( - URL.createObjectURL(new Blob([key], { type: "application/json" })), - version - ); - this.#ids.set(key, id); - return id; - } - - has(id: GraphUUID) { - return this.#entries.has(id); - } - - add(graph: GraphDescriptor, version: number) { - const id = this.#getOrSetGraphId(graph, version); - if (this.#entries.has(id)) return { id, added: false }; - this.#entries.set(id, graph); - return { id, added: true }; - } - - get(id: GraphUUID) { - return this.#entries.get(id); - } -} diff --git a/packages/breadboard/src/inspector/graph.ts b/packages/breadboard/src/inspector/graph.ts deleted file mode 100644 index 29b8e9ab3ac..00000000000 --- a/packages/breadboard/src/inspector/graph.ts +++ /dev/null @@ -1,411 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphMetadata, - InputValues, - StartLabel, -} from "@google-labs/breadboard-schema/graph.js"; -import { getHandler } from "../handler.js"; -import { createLoader } from "../loader/index.js"; -import { combineSchemas, removeProperty } from "../schema.js"; -import { - Edge, - GraphDescriptor, - NodeDescriberContext, - NodeDescriberFunction, - NodeDescriberResult, - NodeHandler, - NodeIdentifier, - NodeTypeIdentifier, - Schema, -} from "../types.js"; -import { EdgeCache } from "./edge.js"; -import { collectKits, createGraphNodeType } from "./kits.js"; -import { NodeCache } from "./node.js"; -import { - EdgeType, - describeInput, - describeOutput, - edgesToSchema, -} from "./schemas.js"; -import { - InspectableEdge, - MutableGraph, - InspectableGraphOptions, - InspectableGraphWithStore, - InspectableKit, - InspectableNode, - InspectableSubgraphs, - NodeTypeDescriberOptions, - InspectableNodeType, -} from "./types.js"; -import { invokeGraph } from "../run/invoke-graph.js"; -import { graphUrlLike } from "../utils/graph-url-like.js"; - -export const inspectableGraph = ( - graph: GraphDescriptor, - options?: InspectableGraphOptions -): InspectableGraphWithStore => { - return new Graph(graph, options); -}; - -const maybeURL = (url?: string): URL | undefined => { - url = url || ""; - try { - return new URL(url); - } catch { - return undefined; - } -}; - -type CustomDescriberResult = - | { - success: true; - result: NodeDescriberResult; - } - | { - success: false; - }; - -class Graph implements InspectableGraphWithStore { - #url?: URL; - #kits?: InspectableKit[]; - #nodeTypes?: Map; - #options: InspectableGraphOptions; - - #graph: GraphDescriptor; - #cache: MutableGraph; - #graphs: InspectableSubgraphs | null = null; - - constructor(graph: GraphDescriptor, options?: InspectableGraphOptions) { - this.#graph = graph; - this.#url = maybeURL(graph.url); - this.#options = options || {}; - const nodes = new NodeCache(this); - const edges = new EdgeCache(nodes); - edges.populate(graph); - this.#cache = { edges, nodes }; - } - - raw() { - return this.#graph; - } - - metadata(): GraphMetadata | undefined { - return this.#graph.metadata; - } - - nodesByType(type: NodeTypeIdentifier): InspectableNode[] { - return this.#cache.nodes.byType(type); - } - - async #getDescriber( - type: NodeTypeIdentifier - ): Promise { - const { kits } = this.#options; - const loader = this.#options.loader || createLoader(); - let handler: NodeHandler | undefined; - try { - handler = await getHandler(type, { - kits, - loader, - }); - } catch (e) { - console.warn(`Error getting describer for node type ${type}`, e); - } - if (!handler || !("describe" in handler) || !handler.describe) { - return undefined; - } - return handler.describe; - } - - async describeType( - type: NodeTypeIdentifier, - options: NodeTypeDescriberOptions = {} - ): Promise { - // The schema of an input or an output is defined by their - // configuration schema or their incoming/outgoing edges. - if (type === "input") { - return describeInput(options); - } - if (type === "output") { - return describeOutput(options); - } - - const { kits } = this.#options; - const describer = await this.#getDescriber(type); - const asWired = { - inputSchema: edgesToSchema(EdgeType.In, options?.incoming), - outputSchema: edgesToSchema(EdgeType.Out, options?.outgoing), - } satisfies NodeDescriberResult; - if (!describer) { - return asWired; - } - const loader = this.#options.loader || createLoader(); - const context: NodeDescriberContext = { - outerGraph: this.#graph, - loader, - kits, - wires: { - incoming: Object.fromEntries( - (options?.incoming ?? []).map((edge) => [ - edge.in, - { - outputPort: { - describe: async () => (await edge.outPort()).type.schema, - }, - }, - ]) - ), - outgoing: Object.fromEntries( - (options?.outgoing ?? []).map((edge) => [ - edge.out, - { - inputPort: { - describe: async () => (await edge.inPort()).type.schema, - }, - }, - ]) - ), - }, - }; - if (this.#url) { - context.base = this.#url; - } - try { - return describer( - options?.inputs || undefined, - asWired.inputSchema, - asWired.outputSchema, - context - ); - } catch (e) { - console.warn(`Error describing node type ${type}`, e); - return asWired; - } - } - - nodeById(id: NodeIdentifier) { - return this.#cache.nodes.get(id); - } - - nodes(): InspectableNode[] { - return this.#cache.nodes.nodes(); - } - - edges(): InspectableEdge[] { - return this.#cache.edges.edges(); - } - - hasEdge(edge: Edge): boolean { - return this.#cache.edges.hasByValue(edge); - } - - kits(): InspectableKit[] { - return (this.#kits ??= collectKits( - { kits: this.#options.kits, loader: this.#options.loader }, - this.#graph.nodes - )); - } - - typeForNode(id: NodeIdentifier): InspectableNodeType | undefined { - const node = this.nodeById(id); - if (!node) { - return undefined; - } - return this.typeById(node.descriptor.type); - } - - typeById(id: NodeTypeIdentifier): InspectableNodeType | undefined { - const kits = this.kits(); - this.#nodeTypes ??= new Map( - kits.flatMap((kit) => kit.nodeTypes.map((type) => [type.type(), type])) - ); - const knownNodeType = this.#nodeTypes.get(id); - if (knownNodeType) { - return knownNodeType; - } - if (!graphUrlLike(id)) { - return undefined; - } - return createGraphNodeType(id, this.#options); - } - - incomingForNode(id: NodeIdentifier): InspectableEdge[] { - return this.#graph.edges - .filter((edge) => edge.to === id) - .map((edge) => this.#cache.edges.getOrCreate(edge)); - } - - outgoingForNode(id: NodeIdentifier): InspectableEdge[] { - return this.#graph.edges - .filter((edge) => edge.from === id) - .map((edge) => this.#cache.edges.getOrCreate(edge)); - } - - entries(label?: StartLabel): InspectableNode[] { - return this.#cache.nodes.nodes().filter((node) => node.isEntry(label)); - } - - async #describeWithStaticAnalysis(): Promise { - const inputSchemas = ( - await Promise.all( - this.nodesByType("input") - .filter((n) => n.isEntry()) - .map((input) => - describeInput({ - inputs: input.configuration(), - incoming: input.incoming(), - outgoing: input.outgoing(), - asType: true, - }) - ) - ) - ).map((result) => result.outputSchema); - - const outputSchemas = ( - await Promise.all( - this.nodesByType("output") - .filter((n) => n.isExit()) - .map((output) => - describeOutput({ - inputs: output.configuration(), - incoming: output.incoming(), - outgoing: output.outgoing(), - asType: true, - }) - ) - ) - ) - .map((result) => - result.inputSchema.behavior?.includes("bubble") - ? null - : result.inputSchema - ) - .filter(Boolean) as Schema[]; - - const inputSchema = combineSchemas(inputSchemas, (result, schema) => { - if (schema.additionalProperties !== false) { - result.additionalProperties = true; - } else if (!("additionalProperties" in result)) { - result.additionalProperties = false; - } - }); - const outputSchema = removeProperty( - combineSchemas(outputSchemas), - "schema" - ); - - return { inputSchema, outputSchema }; - } - - async #tryDescribingWithCustomDescriber( - inputs: InputValues - ): Promise { - const customDescriber = this.#graph.metadata?.describer; - if (!customDescriber) { - return { success: false }; - } - // invoke graph - try { - const base = this.#url; - // try loading the describer graph. - const { loader } = this.#options; - if (!loader) { - return { success: false }; - } - const describerGraph = await loader.load(customDescriber, { - base, - board: this.#graph, - outerGraph: this.#graph, - }); - if (!describerGraph) { - console.warn( - `Could not load custom describer graph ${customDescriber}` - ); - return { success: false }; - } - const { inputSchema: $inputSchema, outputSchema: $outputSchema } = - await this.#describeWithStaticAnalysis(); - // Remove the artifacts of the describer from the input/output schemas. - // TODO: The right fix here is for static describer to not include - // describer outputs. - // delete $outputSchema.properties?.inputSchema; - // delete $outputSchema.properties?.outputSchema; - const result = (await invokeGraph( - describerGraph, - { ...inputs, $inputSchema, $outputSchema }, - { - base, - kits: this.#options.kits, - loader, - } - )) as NodeDescriberResult; - if ("$error" in result) { - console.warn( - `Error while invoking graph's custom describer`, - result.$error - ); - return { success: false }; - } - if (!result.inputSchema || !result.outputSchema) { - console.warn( - `Custom describer did not return input/output schemas`, - result - ); - return { success: false }; - } - return { success: true, result }; - } catch (e) { - console.warn(`Error while invoking graph's custom describer`, e); - return { success: false }; - } - } - - async describe(inputs?: InputValues): Promise { - const result = await this.#tryDescribingWithCustomDescriber(inputs || {}); - if (result.success) { - return result.result; - } - return this.#describeWithStaticAnalysis(); - } - - get nodeStore() { - return this.#cache.nodes; - } - - get edgeStore() { - return this.#cache.edges; - } - - updateGraph(graph: GraphDescriptor): void { - this.#graph = graph; - } - - resetGraph(graph: GraphDescriptor): void { - this.#graph = graph; - const nodes = new NodeCache(this); - const edges = new EdgeCache(nodes); - edges.populate(graph); - this.#cache = { edges, nodes }; - this.#graphs = null; - } - - #populateSubgraphs(): InspectableSubgraphs { - const subgraphs = this.#graph.graphs; - if (!subgraphs) return {}; - return Object.fromEntries( - Object.entries(subgraphs).map(([id, descriptor]) => { - return [id, new Graph(descriptor, this.#options)]; - }) - ); - } - - graphs(): InspectableSubgraphs { - return (this.#graphs ??= this.#populateSubgraphs()); - } -} diff --git a/packages/breadboard/src/inspector/index.ts b/packages/breadboard/src/inspector/index.ts deleted file mode 100644 index 6d0b200dd8e..00000000000 --- a/packages/breadboard/src/inspector/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export { - createDefaultRunStore, - createDefaultDataStore, -} from "../data/index.js"; -import { GraphDescriptor } from "../types.js"; -import { GraphStore } from "./graph-store.js"; -import { inspectableGraph } from "./graph.js"; -import { RunObserver } from "./run/run.js"; -import { - InspectableGraph, - InspectableGraphOptions, - InspectableRunObserver, - RunObserverOptions, -} from "./types.js"; - -export const inspect = ( - graph: GraphDescriptor, - options?: InspectableGraphOptions -): InspectableGraph => { - return inspectableGraph(graph, options); -}; - -export const createRunObserver = ( - options?: RunObserverOptions -): InspectableRunObserver => { - const store = new GraphStore(); - return new RunObserver(store, options || {}); -}; - -export { Run } from "./run/run.js"; diff --git a/packages/breadboard/src/inspector/kits.ts b/packages/breadboard/src/inspector/kits.ts deleted file mode 100644 index 24f8aa1beb7..00000000000 --- a/packages/breadboard/src/inspector/kits.ts +++ /dev/null @@ -1,228 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { getGraphHandler } from "../handler.js"; -import { - NodeHandlers, - NodeHandler, - NodeDescriberResult, - NodeHandlerMetadata, - NodeDescriptor, - NodeHandlerContext, - NodeTypeIdentifier, - NodeHandlerObject, -} from "../types.js"; -import { graphUrlLike } from "../utils/graph-url-like.js"; -import { collectPortsForType } from "./ports.js"; -import { describeInput, describeOutput } from "./schemas.js"; -import { - InspectableKit, - InspectableNodePorts, - InspectableNodeType, - NodeTypeDescriberOptions, -} from "./types.js"; - -const createBuiltInKit = (): InspectableKit => { - return { - descriptor: { - title: "Built-in Kit", - description: "A kit containing built-in Breadboard nodes", - url: "", - }, - nodeTypes: [ - new BuiltInNodeType("input", describeInput, { - title: "Input", - description: "The input node. Use it to request inputs for your board.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/reference/kits/built-in/#the-input-node", - }, - }), - new BuiltInNodeType("output", describeOutput, { - title: "Output", - description: - "The output node. Use it to provide outputs from your board.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/reference/kits/built-in/#the-output-node", - }, - }), - ], - }; -}; - -const createCustomTypesKit = ( - nodes: NodeDescriptor[], - context: NodeHandlerContext -): InspectableKit[] => { - const urlLikeNodeTypes = nodes.filter((node) => graphUrlLike(node.type)); - - const uniqueTypes = [...new Set(urlLikeNodeTypes.map((node) => node.type))]; - if (uniqueTypes.length === 0) { - return []; - } - return [ - { - descriptor: { - title: "Custom Types", - description: "Custom nodes found in the graph", - url: "", - }, - nodeTypes: uniqueTypes.map((type) => { - return new CustomNodeType(type, context); - }), - }, - ]; -}; - -export const collectKits = ( - context: NodeHandlerContext, - nodes: NodeDescriptor[] -): InspectableKit[] => { - const { kits = [] } = context; - return [ - createBuiltInKit(), - ...createCustomTypesKit(nodes, context), - ...kits.map((kit) => { - const descriptor = { - title: kit.title, - description: kit.description, - url: kit.url, - tags: kit.tags || [], - }; - return { - descriptor, - nodeTypes: collectNodeTypes(kit.handlers), - }; - }), - ]; -}; - -export const createGraphNodeType = ( - type: NodeTypeIdentifier, - context: NodeHandlerContext -): InspectableNodeType => { - return new CustomNodeType(type, context); -}; - -const collectNodeTypes = (handlers: NodeHandlers): InspectableNodeType[] => { - return Object.entries(handlers) - .sort() - .map(([type, handler]) => new KitNodeType(type, handler)); -}; - -const portsFromHandler = async ( - type: NodeTypeIdentifier, - handler: NodeHandler | undefined -): Promise => { - if (!handler || typeof handler === "function" || !handler.describe) { - return emptyPorts(); - } - try { - const described = await handler.describe(); - return { - inputs: { - fixed: described.inputSchema.additionalProperties === false, - ports: collectPortsForType(described.inputSchema, "input"), - }, - outputs: { - fixed: described.outputSchema.additionalProperties === false, - ports: collectPortsForType(described.outputSchema, "output"), - }, - }; - } catch (e) { - console.warn(`Error describing node type ${type}:`, e); - return emptyPorts(); - } -}; - -class KitNodeType implements InspectableNodeType { - #type: string; - #handler: NodeHandler; - - constructor(type: string, handler: NodeHandler) { - this.#type = type; - this.#handler = handler; - } - - async metadata(): Promise { - return "metadata" in this.#handler ? this.#handler.metadata || {} : {}; - } - - type() { - return this.#type; - } - - async ports(): Promise { - return portsFromHandler(this.#type, this.#handler); - } -} - -class BuiltInNodeType extends KitNodeType { - constructor( - type: string, - describer: (options: NodeTypeDescriberOptions) => NodeDescriberResult, - metadata: NodeHandlerMetadata - ) { - super(type, { - invoke: async () => {}, - describe: async () => { - return describer({}); - }, - metadata, - }); - } -} - -export const emptyPorts = (): InspectableNodePorts => ({ - inputs: { - ports: [], - fixed: false, - }, - outputs: { - ports: [], - fixed: false, - }, -}); - -function shortUrlTitle(url: string) { - const urlObj = new URL(url); - const path = urlObj.pathname.split("/").pop(); - return path || urlObj.host; -} - -class CustomNodeType implements InspectableNodeType { - #type: string; - #metadata: NodeHandlerMetadata | null = null; - #handlerPromise: Promise | null = null; - - constructor(type: string, context: NodeHandlerContext) { - this.#type = type; - this.#handlerPromise = getGraphHandler(type, context); - } - - async #readMetadata() { - const handler = await this.#handlerPromise; - if (handler && "metadata" in handler && handler.metadata) { - return handler.metadata; - } - return { - title: shortUrlTitle(this.#type), - }; - } - - async metadata(): Promise { - this.#metadata ??= await this.#readMetadata(); - return this.#metadata; - } - - type() { - return this.#type; - } - - async ports(): Promise { - const handler = await this.#handlerPromise; - return portsFromHandler(this.#type, handler as NodeHandler); - } -} diff --git a/packages/breadboard/src/inspector/node.ts b/packages/breadboard/src/inspector/node.ts deleted file mode 100644 index 06470291d6b..00000000000 --- a/packages/breadboard/src/inspector/node.ts +++ /dev/null @@ -1,235 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphDescriptor, - NodeMetadata, - StartLabel, -} from "@google-labs/breadboard-schema/graph.js"; -import { - InputValues, - NodeConfiguration, - NodeDescriberResult, - NodeDescriptor, - NodeIdentifier, - NodeTypeIdentifier, - OutputValues, -} from "../types.js"; -import { collectPorts } from "./ports.js"; -import { EdgeType } from "./schemas.js"; -import { - InspectableEdge, - InspectableGraph, - InspectableNode, - InspectableNodePorts, - InspectableNodeType, - InspectablePortList, - NodeTypeDescriberOptions, -} from "./types.js"; - -class Node implements InspectableNode { - descriptor: NodeDescriptor; - #graph: InspectableGraph; - - constructor(descriptor: NodeDescriptor, graph: InspectableGraph) { - this.descriptor = descriptor; - this.#graph = graph; - } - - title(): string { - return this.descriptor.metadata?.title || this.descriptor.id; - } - - description(): string { - return this.descriptor.metadata?.description || this.title(); - } - - incoming(): InspectableEdge[] { - return this.#graph.incomingForNode(this.descriptor.id); - } - - outgoing(): InspectableEdge[] { - return this.#graph.outgoingForNode(this.descriptor.id); - } - - isEntry(label: StartLabel = "default"): boolean { - const labels = this.startLabels(); - if (labels) { - return labels.includes(label); - } else if (label !== "default") { - return false; - } - return this.incoming().length === 0; - } - - startLabels(): StartLabel[] | undefined { - const tags = this.descriptor?.metadata?.tags || []; - const labels: StartLabel[] = []; - for (const tag of tags) { - if (typeof tag === "string" && tag === "start") { - labels.push("default"); - } else if (tag.type === "start") { - labels.push(tag.label || "default"); - } - } - return labels.length > 0 ? labels : undefined; - } - - isExit(): boolean { - return this.outgoing().length === 0; - } - - type(): InspectableNodeType { - const type = this.#graph.typeForNode(this.descriptor.id); - if (!type) { - throw new Error( - `Possible integrity error: node ${this.descriptor.id} does not have a type` - ); - } - return type; - } - - configuration(): NodeConfiguration { - return this.descriptor.configuration || {}; - } - - metadata(): NodeMetadata { - return this.descriptor.metadata || {}; - } - - #inputsAndConfig(inputs?: InputValues, config?: NodeConfiguration) { - // Config first, then inputs on top. Inputs override config. - return { ...config, ...inputs }; - } - - async #describeInternal( - options: NodeTypeDescriberOptions - ): Promise { - return this.#graph.describeType(this.descriptor.type, { - inputs: this.#inputsAndConfig(options.inputs, this.configuration()), - incoming: options.incoming, - outgoing: options.outgoing, - }); - } - - async describe(inputs?: InputValues): Promise { - return this.#describeInternal({ - inputs, - incoming: this.incoming(), - outgoing: this.outgoing(), - }); - } - - async ports( - inputValues?: InputValues, - outputValues?: OutputValues - ): Promise { - const incoming = this.incoming(); - const outgoing = this.outgoing(); - const described = await this.#describeInternal({ - inputs: inputValues, - incoming, - outgoing, - }); - const inputs: InspectablePortList = { - fixed: described.inputSchema.additionalProperties === false, - ports: collectPorts( - EdgeType.In, - incoming, - described.inputSchema, - false, - true, - this.#inputsAndConfig(inputValues, this.configuration()) - ), - }; - const addErrorPort = - this.descriptor.type !== "input" && this.descriptor.type !== "output"; - const outputs: InspectablePortList = { - fixed: described.outputSchema.additionalProperties === false, - ports: collectPorts( - EdgeType.Out, - outgoing, - described.outputSchema, - addErrorPort, - false, - outputValues - ), - }; - return { inputs, outputs }; - } -} - -export class NodeCache { - #graph: InspectableGraph; - #map?: Map; - #typeMap?: Map; - - constructor(graph: InspectableGraph) { - this.#graph = graph; - } - - populate(graph: GraphDescriptor) { - graph.nodes.forEach((node) => this.#addNodeInternal(node)); - } - - #addNodeInternal(node: NodeDescriptor) { - this.#typeMap ??= new Map(); - this.#map ??= new Map(); - const inspectableNode = new Node(node, this.#graph); - const type = node.type; - let list = this.#typeMap.get(type); - if (!list) { - list = []; - this.#typeMap.set(type, list); - } - list.push(inspectableNode); - this.#map.set(node.id, inspectableNode); - return inspectableNode; - } - - #ensureNodeMap() { - if (this.#map) return this.#map; - this.populate(this.#graph.raw()); - this.#map ??= new Map(); - return this.#map!; - } - - byType(type: NodeTypeIdentifier): InspectableNode[] { - this.#ensureNodeMap(); - return this.#typeMap?.get(type) || []; - } - - get(id: string): InspectableNode | undefined { - return this.#ensureNodeMap().get(id); - } - - add(node: NodeDescriptor) { - if (!this.#map) { - return; - } - console.assert(!this.#map.has(node.id), "Node already exists in cache."); - this.#addNodeInternal(node); - } - - remove(id: NodeIdentifier) { - if (!this.#map) { - return; - } - const node = this.#map.get(id); - console.assert(node, "Node does not exist in cache."); - const type = node!.descriptor.type; - const list = this.#typeMap?.get(type); - if (list) { - const index = list.indexOf(node!); - list.splice(index, 1); - } - this.#map.delete(id); - } - - nodes(): InspectableNode[] { - return Array.from(this.#ensureNodeMap().values()); - } -} diff --git a/packages/breadboard/src/inspector/ports.ts b/packages/breadboard/src/inspector/ports.ts deleted file mode 100644 index 3e8de2dcbd5..00000000000 --- a/packages/breadboard/src/inspector/ports.ts +++ /dev/null @@ -1,214 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { analyzeIsJsonSubSchema } from "@google-labs/breadboard-schema/subschema.js"; -import { JSONSchema4 } from "json-schema"; -import { BehaviorSchema, NodeConfiguration, Schema } from "../types.js"; -import { DEFAULT_SCHEMA, EdgeType } from "./schemas.js"; -import { - CanConnectAnalysis, - InspectableEdge, - InspectablePort, - InspectablePortType, - PortStatus, -} from "./types.js"; - -const title = (schema: Schema, key: string) => { - return schema.properties?.[key]?.title || key; -}; - -export const computePortStatus = ( - wired: boolean, - expected: boolean, - required: boolean, - wiredContainsStar: boolean -): PortStatus => { - if (wired) { - if (expected) return PortStatus.Connected; - return wiredContainsStar ? PortStatus.Indeterminate : PortStatus.Dangling; - } - if (required) { - return wiredContainsStar ? PortStatus.Indeterminate : PortStatus.Missing; - } - return PortStatus.Ready; -}; - -/** - * A mapping from each Breadboard behavior to whether or not that behavior - * matters for type-checking. - */ -const BEHAVIOR_AFFECTS_TYPE_CHECKING: { [K in BehaviorSchema]: boolean } = { - deprecated: false, - transient: false, - config: false, - "google-drive-query": false, - "google-drive-file-id": false, - - // TODO(aomarks) Not sure about many of these. Some affect the data type, some - // only affect formatting? - bubble: true, - board: true, - stream: true, - error: true, - "llm-content": true, - "json-schema": true, - "ports-spec": true, - image: true, - code: true, -}; - -export const collectPorts = ( - type: EdgeType, - edges: InspectableEdge[], - schema: Schema, - addErrorPort: boolean, - allowRequired: boolean, - values?: NodeConfiguration -) => { - let wiredContainsStar = false; - // Get the list of all ports wired to this node. - const wiredPortNames = edges.map((edge) => { - if (edge.out === "*") { - wiredContainsStar = true; - return "*"; - } - return type === EdgeType.In ? edge.in : edge.out; - }); - const fixed = schema.additionalProperties === false; - const schemaPortNames = Object.keys(schema.properties || {}); - if (addErrorPort) { - // Even if not specified in the schema, all non-built-in nodes always have - // an optional `$error` port. - schemaPortNames.push("$error"); - } - const schemaContainsStar = schemaPortNames.includes("*"); - const requiredPortNames = schema.required || []; - const valuePortNames = Object.keys(values || {}); - const portNames = [ - ...new Set([ - ...wiredPortNames, - ...schemaPortNames, - ...valuePortNames, - "*", // Always include the star port. - "", // Always include the control port. - ]), - ]; - portNames.sort(); - return portNames - .map((port) => { - const star = port === "*" || port === ""; - const configured = valuePortNames.includes(port); - const wired = wiredPortNames.includes(port); - const expected = schemaPortNames.includes(port) || star; - const required = requiredPortNames.includes(port); - const portSchema = schema.properties?.[port] || DEFAULT_SCHEMA; - if (portSchema.behavior?.includes("deprecated") && !wired) return null; - return { - name: port, - title: title(schema, port), - configured, - value: values?.[port], - star, - get edges() { - if (!wired) return []; - return edges.filter((edge) => { - if (edge.out === "*" && star) return true; - return type === EdgeType.In ? edge.in === port : edge.out === port; - }); - }, - status: computePortStatus( - wired || configured, - !fixed || expected || schemaContainsStar, - allowRequired && required, - wiredContainsStar - ), - schema: portSchema, - type: new PortType(portSchema), - kind: type === EdgeType.In ? "input" : "output", - } satisfies InspectablePort; - }) - .filter(Boolean) as InspectablePort[]; -}; - -export class PortType implements InspectablePortType { - constructor(public schema: Schema) {} - - hasBehavior(behavior: BehaviorSchema): boolean { - return !!this.schema.behavior?.includes(behavior); - } - - canConnect(to: InspectablePortType): boolean { - return this.analyzeCanConnect(to).canConnect; - } - - analyzeCanConnect(to: InspectablePortType): CanConnectAnalysis { - // Check standard JSON Schema subset rules. - const subSchemaAnalysis = analyzeIsJsonSubSchema( - this.schema as JSONSchema4, - to.schema as JSONSchema4 - ); - if (!subSchemaAnalysis.isSubSchema) { - return { - canConnect: false, - details: subSchemaAnalysis.details.map((detail) => ({ - message: "Incompatible schema", - detail: { - outputPath: detail.pathA, - inputPath: detail.pathB, - }, - })), - }; - } - // Check Breadboard-specific behaviors. - const fromBehaviors = new Set(this.schema.behavior); - for (const toBehavior of to.schema.behavior ?? []) { - if ( - BEHAVIOR_AFFECTS_TYPE_CHECKING[toBehavior] && - !fromBehaviors.has(toBehavior) - ) { - return { - canConnect: false, - details: [ - { - message: "Incompatible behaviors", - detail: { outputPath: ["behavior"], inputPath: ["behavior"] }, - }, - ], - }; - } - } - return { canConnect: true }; - } -} - -export const collectPortsForType = ( - schema: Schema, - kind: "input" | "output" -): InspectablePort[] => { - const portNames = Object.keys(schema.properties || {}); - const requiredPortNames = schema.required || []; - portNames.sort(); - return portNames.map((port) => { - const portSchema: Schema = schema.properties?.[port] || DEFAULT_SCHEMA; - return { - name: port, - title: title(schema, port), - configured: false, - star: false, - edges: [], - value: null, - status: computePortStatus( - false, - true, - requiredPortNames.includes(port), - false - ), - schema: portSchema, - type: new PortType(portSchema), - kind, - } satisfies InspectablePort; - }); -}; diff --git a/packages/breadboard/src/inspector/run/conversions.ts b/packages/breadboard/src/inspector/run/conversions.ts deleted file mode 100644 index 4dbf4a24c6a..00000000000 --- a/packages/breadboard/src/inspector/run/conversions.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export const eventIdFromEntryId = (entryId?: string): string => { - return `e-${entryId || "0"}`; -}; - -export const entryIdFromEventId = (eventId?: string): string | null => { - return eventId?.startsWith("e-") ? eventId.substring(2) : null; -}; - -export const idFromPath = (path: number[]): string => { - return path.join("-"); -}; - -export const pathFromId = (id: string): number[] => { - return id.length ? id.split("-").map((s) => parseInt(s, 10)) : []; -}; diff --git a/packages/breadboard/src/inspector/run/event-manager.ts b/packages/breadboard/src/inspector/run/event-manager.ts deleted file mode 100644 index 3a9944aed46..00000000000 --- a/packages/breadboard/src/inspector/run/event-manager.ts +++ /dev/null @@ -1,308 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult, SecretResult } from "../../harness/types.js"; -import { - EdgeResponse, - ErrorResponse, - GraphEndProbeData, - GraphStartProbeData, - InputResponse, - NodeDescriptor, - NodeEndResponse, - NodeStartResponse, - OutputResponse, -} from "../../types.js"; -import { inspectableGraph } from "../graph.js"; -import { - ERROR_PATH, - PathRegistry, - SECRET_PATH, - createSimpleEntry, -} from "./path-registry.js"; -import { RunNodeEvent } from "./run-node-event.js"; -import { RunSerializer, SequenceEntry } from "./serializer.js"; -import { - EventIdentifier, - GraphDescriptorStore, - InspectableRunEdge, - InspectableRunErrorEvent, - InspectableRunEvent, - InspectableRunNodeEvent, - InspectableRunSecretEvent, - PathRegistryEntry, - RunObserverLogLevel, - RunObserverOptions, - RunSerializationOptions, - TimelineEntry, -} from "../types.js"; -import { SerializedDataStoreGroup } from "../../data/types.js"; -import { - entryIdFromEventId, - eventIdFromEntryId, - idFromPath, - pathFromId, -} from "./conversions.js"; - -const shouldSkipEvent = ( - options: RunObserverOptions, - node: NodeDescriptor, - isTopLevel: boolean -): boolean => { - // Never skip input or output events. - if (isTopLevel && (node.type === "input" || node.type === "output")) - return false; - - const isAskingForDebug = !!options.logLevel && options.logLevel == "debug"; - // If asking for debug, show all events, regardless of the node's log level. - if (isAskingForDebug) return false; - - const nodelogLevel = - (node.metadata?.logLevel as RunObserverLogLevel) || "debug"; - return nodelogLevel !== "info"; -}; - -export class EventManager { - #graphStore; - #options; - #pathRegistry = new PathRegistry(); - #serializer = new RunSerializer(); - #sequence: SequenceEntry[] = []; - #currentNodeEvent: RunNodeEvent | null = null; - - constructor(store: GraphDescriptorStore, options: RunObserverOptions) { - this.#graphStore = store; - this.#options = options; - } - - #addToSequence(type: TimelineEntry[0], entry: PathRegistryEntry) { - this.#sequence.push([type, entry]); - } - - #addGraphstart(data: GraphStartProbeData) { - const { path, graph, timestamp } = data; - const { id: graphId } = this.#graphStore.add(graph, 0); - const entry = this.#pathRegistry.create(path); - entry.graphId = graphId; - entry.graphStart = timestamp; - entry.view = { - // Math: The start index is the length of the sequence before the - // graphstart event is added. - start: this.#sequence.length, - sequence: this.#sequence, - }; - // TODO: Instead of creating a new instance, cache and store them - // in the GraphStore. - entry.graph = inspectableGraph(graph, { kits: this.#options.kits }); - this.#addToSequence("graphstart", entry); - } - - #addGraphend(data: GraphEndProbeData) { - const { path, timestamp } = data; - const entry = this.#pathRegistry.find(path); - if (!entry) { - if (path.length > 0) { - throw new Error( - `Expected an existing entry for ${JSON.stringify(path)}` - ); - } - return; - } - entry.graphEnd = timestamp; - this.#addToSequence("graphend", entry); - } - - #addEdge(data: EdgeResponse) { - const { edge, to, value: allValues } = data; - const entry = this.#pathRegistry.create(to.slice(0, -1)); - // Only store the value for this particular edge. - let value = allValues; - if (!edge.in) { - if (!edge.out) { - value = undefined; - } - } else { - const edgeValue = allValues ? allValues[edge.in] : null; - value = edgeValue ? { [edge.in]: edgeValue } : undefined; - } - entry.edges.push({ ...data, value }); - } - - #addNodestart(data: NodeStartResponse) { - const { node, timestamp, inputs, path } = data; - const entry = this.#pathRegistry.create(path); - - if (!entry) { - throw new Error(`Expected an existing entry for ${JSON.stringify(path)}`); - } - - const event = new RunNodeEvent(entry, node.id, timestamp, inputs); - event.hidden = shouldSkipEvent( - this.#options, - node, - entry.path.length === 1 - ); - entry.event = event; - this.#addToSequence("nodestart", entry); - this.#currentNodeEvent = event; - } - - #addInput(data: InputResponse) { - const { path, bubbled, inputArguments, node, timestamp } = data; - const entry = this.#pathRegistry.find(path); - if (!entry) { - throw new Error(`Expected an existing entry for ${JSON.stringify(path)}`); - } - - if (bubbled) { - const event = new RunNodeEvent(entry, node.id, timestamp, inputArguments); - event.bubbled = true; - this.#pathRegistry.addSidecar(path, event); - this.#addToSequence("input", createSimpleEntry(path, event)); - } else { - const existing = entry.event; - if (!existing) { - console.error("Expected an existing event for", path); - return; - } - this.#addToSequence("input", entry); - } - } - - #addOutput(data: OutputResponse) { - const { path, bubbled, node, timestamp, outputs } = data; - const entry = this.#pathRegistry.find(path); - if (!entry) { - throw new Error(`Expected an existing entry for ${JSON.stringify(path)}`); - } - if (bubbled) { - const event = new RunNodeEvent(entry, node.id, timestamp, outputs); - event.bubbled = true; - this.#pathRegistry.addSidecar(path, event); - this.#addToSequence("output", createSimpleEntry(path, event)); - } else { - const existing = entry.event; - if (!existing) { - console.error("Expected an existing event for", path); - return; - } - if (existing.type !== "node") { - throw new Error( - `Expected an existing event to be of type "node", but got ${existing.type}` - ); - } - existing.inputs = data.outputs; - this.#addToSequence("output", entry); - } - } - - #addNodeend(data: NodeEndResponse) { - const { path } = data; - const entry = this.#pathRegistry.find(path); - if (!entry) { - throw new Error(`Expected an existing entry for ${JSON.stringify(path)}`); - } - const existing = entry.event; - if (!existing) { - // This is an event that was skipped because the log levels didn't - // match. - this.#pathRegistry.finalizeSidecar(path, data); - return; - } - if (existing.type !== "node") { - throw new Error( - `Expected an existing event to be of type "node", but got ${existing.type}` - ); - } - existing.end = data.timestamp; - existing.outputs = data.outputs; - this.#pathRegistry.finalizeSidecar(path, data); - this.#addToSequence("nodeend", entry); - } - - #addSecret(data: SecretResult["data"]) { - const { timestamp: start, keys } = data; - const id = idFromPath(SECRET_PATH); - const event: InspectableRunSecretEvent = { - id: eventIdFromEntryId(id), - type: "secret", - keys, - start, - end: null, - }; - this.#pathRegistry.addSidecar(SECRET_PATH, event); - this.#addToSequence("secret", createSimpleEntry(SECRET_PATH, event)); - } - - #addError(data: ErrorResponse) { - const { timestamp: start, error } = data; - const id = idFromPath(ERROR_PATH); - const event: InspectableRunErrorEvent = { - id: eventIdFromEntryId(id), - type: "error", - start, - error, - }; - this.#pathRegistry.addError(event); - this.#addToSequence("error", createSimpleEntry(ERROR_PATH, event)); - } - - add(result: HarnessRunResult) { - this.#pathRegistry.finalizeSidecar(SECRET_PATH, result.data); - - switch (result.type) { - case "graphstart": - return this.#addGraphstart(result.data); - case "edge": - return this.#addEdge(result.data); - case "graphend": - return this.#addGraphend(result.data); - case "nodestart": - return this.#addNodestart(result.data); - case "input": - return this.#addInput(result.data); - case "output": - return this.#addOutput(result.data); - case "secret": - return this.#addSecret(result.data); - case "nodeend": - return this.#addNodeend(result.data); - case "error": - return this.#addError(result.data); - } - } - - get events(): InspectableRunEvent[] { - return this.#pathRegistry.events; - } - - get edges(): InspectableRunEdge[] { - return this.#pathRegistry.edges; - } - - currentEvent(): InspectableRunNodeEvent | null { - return this.#currentNodeEvent; - } - - serialize( - data: SerializedDataStoreGroup | null, - options: RunSerializationOptions - ) { - return this.#serializer.serialize(this.#sequence, data, options); - } - - serializer() { - return this.#serializer; - } - - getEventById(id: EventIdentifier): InspectableRunEvent | null { - const entryId = entryIdFromEventId(id); - if (!entryId) return null; - const path = pathFromId(entryId); - const entry = this.#pathRegistry.find(path); - return entry?.event || null; - } -} diff --git a/packages/breadboard/src/inspector/run/loader.ts b/packages/breadboard/src/inspector/run/loader.ts deleted file mode 100644 index 8aa1c9cdce9..00000000000 --- a/packages/breadboard/src/inspector/run/loader.ts +++ /dev/null @@ -1,173 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "../../harness/types.js"; -import { replaceSecrets } from "./serializer.js"; -import { - GraphstartTimelineEntry, - InspectableGraph, - InspectableRunLoadResult, - NodestartTimelineEntry, - SerializedRun, - SerializedRunLoadingOptions, - TimelineEntry, -} from "../types.js"; -import { inspectableGraph } from "../graph.js"; -import { DataStore, SerializedDataStoreGroup } from "../../data/types.js"; -import { remapData } from "../../data/inflate-deflate.js"; -import { asyncGen } from "../../utils/async-gen.js"; -import { PastRun } from "./past-run.js"; - -export const errorResult = (error: string): HarnessRunResult => { - return { - type: "error", - data: { - error, - timestamp: Date.now(), - }, - reply: async () => { - // Do nothing - }, - }; -}; - -export class RunLoader { - #run: SerializedRun; - #store: DataStore; - #graphs = new Map(); - #options: SerializedRunLoadingOptions; - - constructor( - store: DataStore, - o: unknown, - options: SerializedRunLoadingOptions - ) { - this.#store = store; - this.#run = o as SerializedRun; - this.#options = options; - } - - #asHarnessRunResult(entry: TimelineEntry): HarnessRunResult { - const [type, data] = entry; - return { type, data } as HarnessRunResult; - } - - async #inflateData( - timeline: TimelineEntry[], - serializedData: SerializedDataStoreGroup - ): Promise { - return await Promise.all( - timeline.map(async (entry) => { - const [, data] = entry; - entry[1] = (await remapData( - this.#store, - data, - serializedData - )) as Promise; - return entry; - }) - ); - } - - loadGraphStart(result: GraphstartTimelineEntry): HarnessRunResult { - const [, data] = result; - const { index, timestamp, path } = data; - let { graph } = data; - if (graph !== null) { - this.#graphs.set(index, inspectableGraph(graph, this.#options ?? {})); - } else { - graph = this.#graphs.get(index)?.raw() || null; - } - return { - type: "graphstart", - data: { timestamp, path, graph }, - } as HarnessRunResult; - } - - loadNodestart(result: NodestartTimelineEntry): HarnessRunResult { - const [, data] = result; - const { graph: graphIndex, id: node, timestamp, inputs, path } = data; - const graph = this.#graphs.get(graphIndex); - if (!graph) { - throw new Error( - `Unknown graph index ${graphIndex} while loading nodestart` - ); - } - const descriptor = graph.nodeById(node); - if (!descriptor) { - throw new Error(`Unknown node id ${node} while loading nodestart`); - } - return { - type: "nodestart", - data: { timestamp, path, inputs, node: descriptor.descriptor }, - } as HarnessRunResult; - } - - async *replay() { - const run = this.#run; - if (run.$schema !== "tbd") { - yield errorResult(`Specified "$schema": "${run.$schema}" is not valid`); - } - yield* asyncGen(async (next) => { - try { - const secretReplacer = this.#options?.secretReplacer; - let timeline = secretReplacer - ? replaceSecrets(run, secretReplacer).timeline - : run.timeline; - timeline = run.data - ? await this.#inflateData(timeline, run.data) - : timeline; - for (const result of timeline) { - const [type] = result; - switch (type) { - case "graphstart": - await next(this.loadGraphStart(result)); - continue; - case "nodestart": - await next(this.loadNodestart(result)); - continue; - default: - await next(this.#asHarnessRunResult(result)); - } - } - } catch (e) { - const error = e as Error; - next(errorResult(`Loading run failed with the error ${error.message}`)); - } - }); - } - - async load(): Promise { - const run = this.#run; - const runId = crypto.randomUUID(); - this.#store.createGroup(runId); - - if (run.$schema !== "tbd") { - return { - success: false, - error: `Specified "$schema" is not valid`, - }; - } - try { - const secretReplacer = this.#options?.secretReplacer; - let timeline = secretReplacer - ? replaceSecrets(run, secretReplacer).timeline - : run.timeline; - timeline = run.data - ? await this.#inflateData(timeline, run.data) - : timeline; - const pastRun = new PastRun(runId, timeline, this.#options); - await pastRun.initializeBackingRun(); - return { success: true, run: pastRun }; - } catch (e) { - const error = e as Error; - return { - success: false, - error: `Loading run failed with the error ${error.message}`, - }; - } - } -} diff --git a/packages/breadboard/src/inspector/run/nested-run.ts b/packages/breadboard/src/inspector/run/nested-run.ts deleted file mode 100644 index b194929d1cc..00000000000 --- a/packages/breadboard/src/inspector/run/nested-run.ts +++ /dev/null @@ -1,214 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; -import { HarnessRunResult } from "../../harness/types.js"; -import type { - EventIdentifier, - GraphUUID, - InspectableRun, - InspectableRunEvent, - InspectableRunInputs, - InspectableRunNodeEvent, - PathRegistryEntry, -} from "../types.js"; -import { entryIdFromEventId, pathFromId } from "./conversions.js"; - -/** - * Meant to be a very lightweight wrapper around the - * data in the `PathRegistryEntry`. - */ -export class NestedRun implements InspectableRun { - public readonly dataStoreKey = Date.now().toFixed(3); - - #entry: PathRegistryEntry; - - graphId: GraphUUID; - start: number; - end: number | null; - graphVersion = 0; - events: InspectableRunEvent[]; - edges = []; - - constructor(entry: PathRegistryEntry) { - this.graphId = entry.graphId as GraphUUID; - this.start = entry.graphStart; - this.end = entry.graphEnd; - this.events = entry.events; - this.#entry = entry; - } - - currentNodeEvent(): InspectableRunNodeEvent | null { - return null; - } - - stack(): InspectableRunNodeEvent[] { - // TODO: Implement stack support for nested runs. - return []; - } - - getEventById(id: EventIdentifier): InspectableRunEvent | null { - const entryId = entryIdFromEventId(id); - if (!entryId) return null; - const path = pathFromId(entryId); - const entry = this.#entry.find(path); - return entry?.event || null; - } - - inputs(): InspectableRunInputs | null { - return null; - } - - async *replay(): AsyncGenerator { - const { view } = this.#entry; - if (!view) { - return; - } - const { sequence, start } = view; - if (!sequence) { - return; - } - const timeline = sequence.slice(start); - const first = timeline[0]; - let endPath: number[] = []; - if (first[0] !== "graphstart") { - throw new Error( - "Expected a graphstart event at the beginning of the timeline" - ); - } else { - endPath = first[1].path; - } - for await (const result of timeline) { - const [type, data] = result; - switch (type) { - case "graphstart": { - const { graphStart, path, graph: inspectableGraph, edges } = data; - const graph = inspectableGraph?.raw() as GraphDescriptor; - yield { - type, - data: { timestamp: graphStart, path: trimPath(path), graph, edges }, - async reply() {}, - }; - break; - } - case "nodestart": { - const { path } = data; - const { - node, - inputs, - start: timestamp, - } = data.event as InspectableRunNodeEvent; - yield { - type, - data: { - node: node.descriptor, - inputs, - path: trimPath(path), - timestamp, - }, - async reply() {}, - }; - break; - } - case "nodeend": { - const { path } = data; - const { - node, - inputs, - outputs, - end: timestamp, - } = data.event as InspectableRunNodeEvent; - yield { - type, - data: { - node: node.descriptor, - inputs, - outputs: outputs || {}, - path: trimPath(path), - timestamp: timestamp || 0, - }, - async reply() {}, - }; - break; - } - case "graphend": { - const { path } = data; - const { graphEnd: timestamp } = data; - yield { - type, - data: { path: trimPath(path), timestamp: timestamp || 0 }, - async reply() {}, - }; - if (path.join(".") === endPath.join(".")) { - return; - } - break; - } - case "error": { - const { graphStart: timestamp } = data; - yield { - type, - data: { error: "TODO: Store actual error object", timestamp }, - async reply() {}, - }; - break; - } - case "input": { - const { path } = data; - const { - node, - inputs: inputArguments, - bubbled, - start: timestamp, - } = data.event as InspectableRunNodeEvent; - yield { - type, - data: { - node: node.descriptor, - inputArguments, - bubbled, - path: trimPath(path), - timestamp, - }, - async reply() {}, - }; - break; - } - case "output": { - const { path } = data; - const { - node, - outputs, - bubbled, - start: timestamp, - } = data.event as InspectableRunNodeEvent; - yield { - type, - data: { - node: node.descriptor, - outputs: outputs || {}, - bubbled, - path: trimPath(path), - timestamp, - }, - async reply() {}, - }; - break; - } - case "secret": { - break; - } - default: { - throw new Error("Unknown event type: " + type); - } - } - } - - function trimPath(path: number[]) { - return path.slice(endPath.length); - } - } -} diff --git a/packages/breadboard/src/inspector/run/past-run.ts b/packages/breadboard/src/inspector/run/past-run.ts deleted file mode 100644 index 914ee771d04..00000000000 --- a/packages/breadboard/src/inspector/run/past-run.ts +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "../../harness/types.js"; -import { GraphStore } from "../graph-store.js"; -import { - EventIdentifier, - GraphUUID, - InspectableRun, - InspectableRunEvent, - InspectableRunInputs, - InspectableRunNodeEvent, - SerializedRunLoadingOptions, - TimelineEntry, -} from "../types.js"; -import { Replay } from "./replay.js"; -import { RunObserver } from "./run.js"; - -export class PastRun implements InspectableRun { - #replay: Replay; - #backingRun: InspectableRun | null = null; - - edges = []; - - constructor( - public readonly dataStoreKey = crypto.randomUUID(), - timeline: TimelineEntry[], - options: SerializedRunLoadingOptions - ) { - this.#replay = new Replay(timeline, 0, options); - } - - async initializeBackingRun() { - const observer = new RunObserver(new GraphStore(), { logLevel: "debug" }); - for await (const result of this.replay()) { - await observer.observe(result); - } - this.#backingRun = (await observer.runs())[0]; - } - - get graphId(): GraphUUID { - if (!this.#backingRun) { - throw new Error("Uninitialized run: can't yet provide graph IDs"); - } - return this.#backingRun.graphId; - } - - get graphVersion(): number { - if (!this.#backingRun) { - throw new Error("Uninitialized run: can't yet provide graph versions"); - } - return this.#backingRun.graphVersion; - } - - get start(): number { - if (!this.#backingRun) { - throw new Error("Uninitialized run: can't yet provide start times"); - } - return this.#backingRun.start; - } - get end(): number | null { - if (!this.#backingRun) { - throw new Error("Uninitialized run: can't yet provide end times"); - } - return this.#backingRun.end; - } - - get events(): InspectableRunEvent[] { - if (!this.#backingRun) { - throw new Error("Uninitialized run: can't yet provide events"); - } - return this.#backingRun.events; - } - - currentNodeEvent(): InspectableRunNodeEvent | null { - if (!this.#backingRun) { - throw new Error( - "Uninitialized run: can't yet provide current node events" - ); - } - return this.#backingRun.currentNodeEvent(); - } - - stack(): InspectableRunNodeEvent[] { - if (!this.#backingRun) { - throw new Error("Uninitialized run: can't yet provide stack traces"); - } - return this.#backingRun.stack(); - } - - getEventById(id: EventIdentifier): InspectableRunEvent | null { - if (!this.#backingRun) { - throw new Error("Uninitialized run: can't yet provide event IDs"); - } - return this.#backingRun.getEventById(id); - } - - inputs(): InspectableRunInputs | null { - if (!this.#backingRun) { - throw new Error("Uninitialized run: can't yet provide inputs"); - } - return this.#backingRun.inputs(); - } - - async *replay(): AsyncGenerator { - yield* this.#replay.replay(); - } -} diff --git a/packages/breadboard/src/inspector/run/path-registry.ts b/packages/breadboard/src/inspector/run/path-registry.ts deleted file mode 100644 index 6d0ca7743eb..00000000000 --- a/packages/breadboard/src/inspector/run/path-registry.ts +++ /dev/null @@ -1,229 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { OutputValues } from "../../types.js"; -import { - GraphUUID, - InspectableGraph, - InspectableRunEdge, - InspectableRunErrorEvent, - InspectableRunEvent, - InspectableRunNodeEvent, - PathRegistryEntry, - SequenceView, -} from "../types.js"; -import { idFromPath } from "./conversions.js"; - -export const SECRET_PATH = [-2]; -export const ERROR_PATH = [-3]; - -export const createSimpleEntry = ( - path: number[], - event: InspectableRunEvent -) => { - const entry: PathRegistryEntry = { - path, - parent: null, - children: [], - graphId: null, - graphStart: 0, - graphEnd: 0, - event, - sidecars: [], - empty: () => true, - events: [], - edges: [], - graph: null, - view: null, - find: () => null, - }; - return entry; -}; - -class Entry implements PathRegistryEntry { - id: string = ""; - parent: PathRegistryEntry | null; - #events: InspectableRunEvent[] = []; - #eventsIsDirty = false; - #children: Entry[] = []; - event: InspectableRunEvent | null = null; - sidecars: InspectableRunEvent[] = []; - // Keep track of some sidecar events so that we can clean them up later. - // We only need to keep track of input and output events, since the - // secret and error do not have a corresponding `nodeend` event. - #trackedSidecars: Map = new Map(); - - graphId: GraphUUID | null = null; - // Wait until `graphstart` event to set the start time. - graphStart: number = 0; - graphEnd: number | null = null; - graph: InspectableGraph | null = null; - edges: InspectableRunEdge[] = []; - view: SequenceView | null = null; - - constructor( - public path: number[], - parent: PathRegistryEntry | null - ) { - this.id = idFromPath(path); - this.parent = parent; - } - - empty(): boolean { - return this.#children.length === 0; - } - - addSidecar(path: number[], event: InspectableRunEvent) { - const key = idFromPath(path); - this.children[this.children.length - 1].sidecars.push(event); - this.#trackedSidecars.set(key, event); - this.#eventsIsDirty = true; - } - - /** - * We handle error specially, because unlike sidecars, errors result - * in stopping the run, and we need to display them at the end of the run. - * @param event -- The error event to add. - */ - addError(event: InspectableRunErrorEvent) { - const entry = this.create([this.#children.length]); - entry.event = event as unknown as InspectableRunNodeEvent; - } - - finalizeSidecar( - path: number[], - data?: { timestamp: number; outputs?: OutputValues } - ) { - const key = idFromPath(path); - const sidecar = this.#trackedSidecars.get(key); - switch (sidecar?.type) { - // These are bubbling inputs and inputs. - case "node": { - if (data) { - sidecar.end = data.timestamp; - sidecar.outputs = data.outputs || null; - } - break; - } - case "secret": { - sidecar.end = data?.timestamp || null; - break; - } - } - this.#trackedSidecars.delete(key); - this.#eventsIsDirty = true; - } - - /** - * The main traversal function for the path registry. It will find the - * entry for the given path, creating it if permitted, and return it. - * - * This function is what builds the graph tree. - * - * @param readonly -- If true, the registry is read-only and will not be - * modified. - * @param registry -- The registry to traverse. Used in recursion. - * @param fullPath -- The full path to the current node. Passed along during - * recursion. - * @param path -- The current path to the node. Used in recursion. - * @returns -- The entry for the given path, or undefined if the path is - * empty or invalid. - */ - #findOrCreate( - readonly: boolean, - fullPath: number[], - path: number[] - ): PathRegistryEntry | null { - // Marking events dirty, because we're about to mutate something within - // this swath of the registry. - if (!readonly) this.#eventsIsDirty = true; - const [head, ...tail] = path; - if (head === undefined) { - return null; - } - let entry = this.#children[head]; - if (!entry) { - if (tail.length !== 0) { - // If you see this message in the console, it's a problem with the - // underlying runner. The runner should always provide paths - // incrementally, so there should never be a situation where we don't - // have a registry entry for an index in the middle of the path. - console.warn("Path registry entry not found for", path, "in", fullPath); - } - if (readonly) { - console.warn("Path registry is read-only. Not adding", fullPath); - return null; - } - entry = this.#children[head] = new Entry(fullPath, this); - } - if (tail.length === 0) { - return entry; - } - return entry.#findOrCreate(readonly, fullPath, tail); - } - - find(path: number[]) { - return this.#findOrCreate(true, path, path); - } - - create(path: number[]) { - return this.#findOrCreate(false, path, path) as Entry; - } - - arrangeSidecars() { - const before: InspectableRunNodeEvent[] = []; - const after: InspectableRunNodeEvent[] = []; - this.sidecars.forEach((sidecar) => { - const event = sidecar as InspectableRunNodeEvent; - if (event.end === null) { - after.push(event); - } else { - before.push(event); - } - }); - if (this.event?.type === "node") { - if (this.event.end !== null && this.event.hidden) { - return null; - } - } - return [...before, this.event, ...after]; - } - - get children() { - return this.#children; - } - - #updateEvents() { - this.#events = this.#children - .filter(Boolean) - .flatMap((entry) => entry.arrangeSidecars()) - .filter(Boolean) as InspectableRunEvent[]; - } - - get events() { - if (this.#eventsIsDirty) { - this.#updateEvents(); - this.#eventsIsDirty = false; - } - return this.#events; - } -} - -export class PathRegistry extends Entry { - constructor() { - super([], null); - } - - override find(path: number[]): PathRegistryEntry | null { - if (path.length == 0) return this; - return super.find(path); - } - - override create(path: number[]): Entry { - if (path.length == 0) return this; - return super.create(path); - } -} diff --git a/packages/breadboard/src/inspector/run/replay.ts b/packages/breadboard/src/inspector/run/replay.ts deleted file mode 100644 index eea4d42cd86..00000000000 --- a/packages/breadboard/src/inspector/run/replay.ts +++ /dev/null @@ -1,134 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "../../harness/types.js"; -import { GraphEndProbeData } from "../../types.js"; -import { asyncGen } from "../../utils/async-gen.js"; -import { inspectableGraph } from "../graph.js"; -import { - GraphstartTimelineEntry, - InspectableGraph, - NodestartTimelineEntry, - SerializedRunLoadingOptions, - TimelineEntry, -} from "../types.js"; - -export { Replay }; - -class Replay { - #timeline: TimelineEntry[]; - #start: number; - #graphs = new Map(); - #options: SerializedRunLoadingOptions; - - constructor( - timeline: TimelineEntry[], - start: number, - options: SerializedRunLoadingOptions = {} - ) { - this.#timeline = timeline; - this.#start = start; - this.#options = options; - } - - #loadGraphStart(result: GraphstartTimelineEntry): HarnessRunResult { - const [, data] = result; - const { index, timestamp, path, edges } = data; - let { graph } = data; - if (graph !== null) { - this.#graphs.set(index, inspectableGraph(graph, this.#options)); - } else { - graph = this.#graphs.get(index)?.raw() || null; - } - return { - type: "graphstart", - data: { timestamp, path, graph, edges }, - } as HarnessRunResult; - } - - #loadNodestart(result: NodestartTimelineEntry): HarnessRunResult { - const [, data] = result; - const { graph: graphIndex, id: node, timestamp, inputs, path } = data; - const graph = this.#graphs.get(graphIndex); - if (!graph) { - throw new Error( - `Unknown graph index ${graphIndex} while loading nodestart` - ); - } - const descriptor = graph.nodeById(node); - if (!descriptor) { - throw new Error(`Unknown node id ${node} while loading nodestart`); - } - return { - type: "nodestart", - data: { timestamp, path, inputs, node: descriptor.descriptor }, - } as HarnessRunResult; - } - - #asHarnessRunResult(entry: TimelineEntry): HarnessRunResult { - const [type, data] = entry; - return { type, data } as HarnessRunResult; - } - - async *replay(): AsyncGenerator { - const isView = this.#start !== 0; - const timeline = this.#timeline.slice(this.#start); - const first = timeline[0]; - let endPath = []; - if (first[0] !== "graphstart") { - throw new Error( - "Expected a graphstart event at the beginning of the timeline" - ); - } else if (isView) { - endPath = first[1].path; - } - yield* asyncGen(async (next) => { - try { - loop: for (const result of timeline) { - const [type] = result; - switch (type) { - case "graphstart": { - await next(this.#loadGraphStart(result)); - continue; - } - case "nodestart": - await next(this.#loadNodestart(result)); - continue; - case "graphend": { - await next(this.#asHarnessRunResult(result)); - if (isView) { - const [, data] = result; - const { path } = data as GraphEndProbeData; - if (path.length === endPath.length) { - break loop; - } - } - break; - } - default: - await next(this.#asHarnessRunResult(result)); - } - } - } catch (e) { - const error = e as Error; - next(errorResult(`Loading run failed with the error ${error.message}`)); - } - }); - } -} - -function errorResult(error: string): HarnessRunResult { - return { - type: "error", - data: { - error, - timestamp: Date.now(), - }, - reply: async () => { - // Do nothing - }, - }; -} diff --git a/packages/breadboard/src/inspector/run/run-node-event.ts b/packages/breadboard/src/inspector/run/run-node-event.ts deleted file mode 100644 index 8bec7d0e42e..00000000000 --- a/packages/breadboard/src/inspector/run/run-node-event.ts +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { HarnessRunResult } from "../../harness/types.js"; -import type { InputValues, NodeIdentifier, OutputValues } from "../../types.js"; -import type { - EventIdentifier, - InspectableGraph, - InspectableNode, - InspectableRun, - InspectableRunNodeEvent, - PathRegistryEntry, -} from "../types.js"; -import { NestedRun } from "./nested-run.js"; -import { BubbledInspectableNode } from "../bubbled-node.js"; -import { eventIdFromEntryId, idFromPath } from "./conversions.js"; - -export class RunNodeEvent implements InspectableRunNodeEvent { - type: "node"; - start: number; - end: number | null; - inputs: InputValues; - outputs: OutputValues | null; - result: HarnessRunResult | null; - bubbled: boolean; - hidden: boolean; - - /** - * The id that will be used to create a `NodeDescriptor`.` - */ - #id: NodeIdentifier; - /** - * The path registry entry associated with this event. - */ - #entry: PathRegistryEntry; - - /** - * A lazily-initialized InspectableNode instance. - */ - #node: InspectableNode | null = null; - - constructor( - entry: PathRegistryEntry, - id: NodeIdentifier, - start: number, - inputs: InputValues - ) { - if (!entry.parent) { - throw new Error( - `RunNodeEvent has no parent entry. This is a bug in Inspector API machinery. Node Id: ${id}` - ); - } - if (!entry.parent.graph) { - throw new Error( - `This node event's parent has no graph associated with it. Node Id: ${id}` - ); - } - - this.#entry = entry; - this.type = "node"; - this.#id = id; - this.start = start; - this.end = null; - this.inputs = inputs; - this.outputs = null; - this.result = null; - this.bubbled = false; - this.hidden = false; - } - - get id(): EventIdentifier { - return eventIdFromEntryId(idFromPath(this.#entry.path)); - } - - get graph(): InspectableGraph { - return this.#entry.parent?.graph as InspectableGraph; - } - - get node(): InspectableNode { - if (this.#node) return this.#node; - - const node = this.graph.nodeById(this.#id); - if (!node) { - throw new Error( - `RunNodeEvent could not find inspectable node. This is a bug in Inspector API machinery. Node Id: ${this.#id}` - ); - } - this.#node = this.bubbled ? new BubbledInspectableNode(node) : node; - return this.#node; - } - - get runs(): InspectableRun[] { - if (this.#entry.empty()) { - return []; - } - const entry = this.#entry; - const events = entry.events; - // a bit of a hack: what I actually need is to find out whether this is - // a map or not. - // Maps have a peculiar structure: their children will have no events, but - // their children's children (the parallel runs) will have events. - if (events.length > 0) { - // This is an ordinary run. - return [new NestedRun(entry)]; - } else { - // This is a map. - return entry.children.filter(Boolean).map((childEntry) => { - return new NestedRun(childEntry); - }); - } - } -} diff --git a/packages/breadboard/src/inspector/run/run.ts b/packages/breadboard/src/inspector/run/run.ts deleted file mode 100644 index 350c171ef0b..00000000000 --- a/packages/breadboard/src/inspector/run/run.ts +++ /dev/null @@ -1,314 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "../../harness/types.js"; -import { GraphDescriptor } from "../../types.js"; -import { EventManager } from "./event-manager.js"; -import { RunLoader } from "./loader.js"; -import { - EventIdentifier, - GraphUUID, - GraphDescriptorStore, - InspectableRun, - InspectableRunEvent, - InspectableRunLoadResult, - InspectableRunObserver, - RunObserverOptions, - RunSerializationOptions, - SerializedRun, - SerializedRunLoadingOptions, - InspectableRunNodeEvent, - InspectableRunInputs, - InspectableRunEdge, -} from "../types.js"; -import { DataStore, RunTimestamp, RunURL } from "../../data/types.js"; - -const isInput = ( - event: InspectableRunEvent -): event is InspectableRunNodeEvent => { - return ( - event.type === "node" && - event.node.descriptor.type === "input" && - event.end !== null - ); -}; - -export class RunObserver implements InspectableRunObserver { - #store: GraphDescriptorStore; - #options: RunObserverOptions; - #runs: InspectableRun[] = []; - #runLimit = 2; - #url: RunURL | null = null; - #timestamp: RunTimestamp | null = null; - - constructor(store: GraphDescriptorStore, options: RunObserverOptions) { - this.#store = store; - this.#options = options; - } - - async runs(): Promise { - return this.#runs; - } - - async #convertRunInfoToRuns( - url: RunURL, - runInfo: Map - ): Promise { - const runs = await Promise.all( - [...runInfo] - .filter(([, events]) => events.length > 0) - .sort(([timeA], [timeB]) => { - return timeB - timeA; - }) - .map(async ([timestamp, results]) => { - let run!: Run; - - for (const result of results) { - if (result.type === "graphstart") { - const { path } = result.data; - if (path.length === 0) { - run = new Run( - timestamp, - this.#store, - result.data.graph, - this.#options - ); - - run.dataStoreKey = `${url}-${timestamp}`; - if (!this.#options.skipDataStore) { - // Ensure that we release old blobs if we've encountered this - // run before. - this.#options.dataStore?.releaseGroup(run.dataStoreKey); - this.#options.dataStore?.createGroup(run.dataStoreKey); - } - } - } else if (result.type === "graphend") { - const { path, timestamp } = result.data; - if (path.length === 0) { - run.end = timestamp; - } - } - - if (!run) { - console.warn("Unable to restore run"); - } - - if (!this.#options.skipDataStore) { - await this.#options.dataStore?.replaceDataParts( - run.dataStoreKey, - result - ); - } - - run.addResult(result); - } - - return run; - }) - ); - - return runs; - } - - async #storeInRunStore( - url: RunURL, - timestamp: RunTimestamp, - result: HarnessRunResult - ) { - const { runStore } = this.#options; - if (!runStore || !this.#url || !this.#timestamp) { - return Promise.resolve(); - } - - if (result.type === "error") { - await runStore?.abort(url, timestamp); - } else { - await runStore?.write(url, timestamp, result); - } - } - - async #loadStoredRuns(url: string): Promise { - let timestamp: RunTimestamp | null = null; - if (!this.#options.runStore) { - return null; - } - timestamp = await this.#options.runStore.start(url); - const runInfo = await this.#options.runStore.getStoredRuns(url); - this.#runs = await this.#convertRunInfoToRuns(url, runInfo); - return timestamp; - } - - async observe(result: HarnessRunResult): Promise { - if (result.type === "graphstart") { - const { path, timestamp } = result.data; - if (path.length === 0) { - this.#url = result.data.graph.url ?? "no-url-graph"; - this.#timestamp = await this.#loadStoredRuns(this.#url); - if (!this.#timestamp) { - this.#timestamp = timestamp; - } - - const run = new Run( - timestamp, - this.#store, - result.data.graph, - this.#options - ); - - if (!this.#options.skipDataStore) { - this.#options.dataStore?.createGroup(run.dataStoreKey); - } - - this.#runs.unshift(run); - - if (this.#options.runStore) { - await this.#options.runStore.truncate(this.#url, this.#runLimit); - } - } - } - - const run = this.#runs[0]; - if (!run) { - console.warn(`No run available to store ${result.type} - stopping`); - return; - } - - if (!this.#url || !this.#timestamp) { - console.warn("No URL or timestamp set for the current run - stopping"); - return; - } - - if (result.type === "graphend") { - const { path, timestamp } = result.data; - if (path.length === 0) { - run.end = timestamp; - } - } - - if (!this.#options.skipDataStore) { - await this.#options.dataStore?.replaceDataParts(run.dataStoreKey, result); - } - - const mutableRun = run as Run; - if ("addResult" in mutableRun) { - mutableRun.addResult(result); - } else { - console.warn( - "Unable to add result to run: this is likely a loaded past run." - ); - return; - } - - await this.#storeInRunStore(this.#url, this.#timestamp, result); - } - - async load( - o: unknown, - options?: SerializedRunLoadingOptions - ): Promise { - if (!this.#options.dataStore) { - throw new Error( - "No data store provided to RunObserver, unable to load runs" - ); - } - const loader = new RunLoader(this.#options.dataStore, o, options || {}); - const result = await loader.load(); - if (result.success) { - this.#runs.push(result.run); - } - return result; - } -} - -export class Run implements InspectableRun { - public dataStoreKey: string = crypto.randomUUID(); - - #events: EventManager; - - graphId: GraphUUID; - start: number; - end: number | null = null; - graphVersion: number; - #dataStore: DataStore | null; - - constructor( - timestamp: number, - graphStore: GraphDescriptorStore, - graph: GraphDescriptor, - options: RunObserverOptions - ) { - this.#events = new EventManager(graphStore, options); - this.#dataStore = options.dataStore || null; - this.graphVersion = 0; - this.start = timestamp; - this.graphId = graphStore.add(graph, this.graphVersion).id; - } - - get events(): InspectableRunEvent[] { - return this.#events.events; - } - - get edges(): InspectableRunEdge[] { - return this.#events.edges; - } - - currentNodeEvent(): InspectableRunNodeEvent | null { - return this.#events.currentEvent(); - } - - stack(): InspectableRunNodeEvent[] { - // TODO: Implement full stack. For now, just return the top-level item. - const getLastNodeEVent = () => { - const events = this.#events.events; - for (let i = events.length - 1; i >= 0; i--) { - const maybeNodeEvent = events[i]; - if (maybeNodeEvent.type === "node" && !maybeNodeEvent.bubbled) - return maybeNodeEvent; - } - return null; - }; - const lastNodeEvent = getLastNodeEVent(); - return lastNodeEvent ? [lastNodeEvent] : []; - } - - addResult(result: HarnessRunResult) { - this.#events.add(result); - } - - async serialize(options?: RunSerializationOptions): Promise { - let data = null; - if (this.#dataStore) { - data = await this.#dataStore.serializeGroup(this.dataStoreKey); - } - - return this.#events.serialize(data, options || {}); - } - - getEventById(id: EventIdentifier): InspectableRunEvent | null { - return this.#events.getEventById(id); - } - - inputs(): InspectableRunInputs | null { - const result: InspectableRunInputs = new Map(); - this.#events.events.forEach((event) => { - if (!isInput(event)) return; - if (event.bubbled) return; - const id = event.node.descriptor.id; - let inputList = result.get(id); - if (!inputList) { - inputList = []; - result.set(id, inputList); - } - inputList.push(event.outputs || {}); - }); - - return result.size > 0 ? result : null; - } - - replay(): AsyncGenerator { - throw new Error("Runs can't yet be replayed."); - } -} diff --git a/packages/breadboard/src/inspector/run/serializer.ts b/packages/breadboard/src/inspector/run/serializer.ts deleted file mode 100644 index d583d9443c4..00000000000 --- a/packages/breadboard/src/inspector/run/serializer.ts +++ /dev/null @@ -1,325 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphDescriptor, - NodeDescriptor, - NodeValue, -} from "@google-labs/breadboard-schema/graph.js"; -import { - GraphUUID, - TimelineEntry, - RunSerializationOptions, - SerializedRun, - SerializedRunSecretReplacer, - PathRegistryEntry, - InspectableRunNodeEvent, - InspectableRunSecretEvent, - InspectableRunErrorEvent, -} from "../types.js"; -import { - ErrorResponse, - GraphEndProbeData, - InputResponse, - NodeEndResponse, - OutputResponse, -} from "../../types.js"; -import { SecretResult } from "../../harness/types.js"; -import { SerializedDataStoreGroup } from "../../data/types.js"; -import { idFromPath } from "./conversions.js"; - -export type SequenceEntry = [type: TimelineEntry[0], entry: PathRegistryEntry]; - -export class RunSerializer { - #seenGraphs = new Map(); - #graphIndex = 0; - - #graphIndexFromEntry(entry: PathRegistryEntry) { - const graphEntry = entry.parent; - if (!graphEntry) { - throw new Error( - `Unknown graph entry for "${idFromPath(entry.path)}" when serializing.` - ); - } - const graphId = graphEntry.graphId; - if (!graphId) { - throw new Error( - `Unknown graphId for "${idFromPath(entry.path)}" when serializing.` - ); - } - const graph = this.#seenGraphs.get(graphId); - if (graph === undefined) { - throw new Error( - `Unknown graph for "${idFromPath(entry.path)}" when serializing.` - ); - } - return graph; - } - - #simpleDescriptor(event: InspectableRunNodeEvent) { - return { id: event.node.descriptor.id } as NodeDescriptor; - } - - serializeGraphstart(entry: PathRegistryEntry): TimelineEntry { - const { graphId } = entry; - if (graphId === null) { - throw new Error("Encountered an empty graphId during graphstart."); - } - let graph: GraphDescriptor | null = null; - let index: number; - if (!this.#seenGraphs.has(graphId)) { - graph = entry.graph?.raw() || null; - index = this.#graphIndex++; - this.#seenGraphs.set(graphId, index); - } else { - index = this.#seenGraphs.get(graphId) || 0; - } - const edges = entry.edges; - return [ - "graphstart", - { - timestamp: entry.graphStart, - path: entry.path, - index, - graph, - edges, - }, - ]; - } - - serializeGraphend(entry: PathRegistryEntry): TimelineEntry { - return [ - "graphend", - { - path: entry.path, - timestamp: entry.graphEnd as number, - } satisfies GraphEndProbeData, - ]; - } - - serializeNodestart(entry: PathRegistryEntry): TimelineEntry { - const event = entry.event as InspectableRunNodeEvent; - const { inputs, start: timestamp } = event; - const node = event.node.descriptor.id; - const graph = this.#graphIndexFromEntry(entry); - return [ - "nodestart", - { id: node, graph, inputs, path: entry.path, timestamp }, - ]; - } - - serializeInput(entry: PathRegistryEntry): TimelineEntry { - const event = entry.event as InspectableRunNodeEvent; - if (!event) { - throw new Error("Unexpected empty input event while serializing run"); - } - return [ - "input", - { - path: entry.path, - timestamp: event.start, // TODO: make sure these match in the runner. - node: this.#simpleDescriptor(event), - inputArguments: event.inputs, - bubbled: event.bubbled, - } satisfies InputResponse, - ]; - } - - serializeOutput(entry: PathRegistryEntry): TimelineEntry { - const event = entry.event as InspectableRunNodeEvent; - if (!event) { - throw new Error("Unexpected empty output event while serializing run"); - } - return [ - "output", - { - path: entry.path, - timestamp: event.start, - node: this.#simpleDescriptor(event), - outputs: event.inputs, - bubbled: event.bubbled, - } satisfies OutputResponse, - ]; - } - - serializeSecret(entry: PathRegistryEntry): TimelineEntry { - const event = entry.event as InspectableRunSecretEvent; - if (!event) { - throw new Error("Unexpected empty secret event while serializing run"); - } - return [ - "secret", - { - keys: event.keys, - timestamp: event.start, - } satisfies SecretResult["data"], - ]; - } - - serializeNodeend(entry: PathRegistryEntry): TimelineEntry { - const event = entry.event as InspectableRunNodeEvent; - if (!event) { - throw new Error("Unexpected empty nodeend event while serializing run"); - } - return [ - "nodeend", - { - path: entry.path, - timestamp: event.end as number, - outputs: event.outputs, - node: { type: event.node.descriptor.type }, - }, - ]; - } - - serializeError(entry: PathRegistryEntry): TimelineEntry { - const event = entry.event as InspectableRunErrorEvent; - if (!event) { - throw new Error("Unexpected empty error event while serializing run"); - } - return [ - "error", - { - error: event.error, - timestamp: event.start, - } satisfies ErrorResponse, - ]; - } - - serialize( - sequence: Iterable, - data: SerializedDataStoreGroup | null, - options: RunSerializationOptions - ) { - const timeline: TimelineEntry[] = []; - for (const [type, entry] of sequence) { - switch (type) { - case "graphstart": { - timeline.push(this.serializeGraphstart(entry)); - break; - } - case "graphend": { - timeline.push(this.serializeGraphend(entry)); - break; - } - case "nodestart": { - timeline.push(this.serializeNodestart(entry)); - break; - } - case "input": { - timeline.push(this.serializeInput(entry)); - break; - } - case "output": { - timeline.push(this.serializeOutput(entry)); - break; - } - case "secret": { - timeline.push(this.serializeSecret(entry)); - break; - } - case "nodeend": { - timeline.push(this.serializeNodeend(entry)); - break; - } - case "error": { - timeline.push(this.serializeError(entry)); - break; - } - } - } - const serialized: SerializedRun = { - $schema: "tbd", - version: "0", - timeline, - }; - if (data) { - serialized.data = data; - } - if (options.keepSecrets) return serialized; - return replaceSecrets(serialized, () => { - return crypto.randomUUID(); - }); - } -} - -export const replaceSecrets = ( - data: SerializedRun, - replacer: SerializedRunSecretReplacer -): SerializedRun => { - const secretStore: Record = {}; - - const serializeSecrets = () => { - return Object.fromEntries( - Object.entries(secretStore).map(([key, value]) => { - return [key, value.to]; - }) - ); - }; - - const processPorts = ( - ports: Record - ): Record => { - if (!ports) return ports; - return Object.fromEntries( - Object.entries(ports).map(([key, value]) => { - let stringified = JSON.stringify(value); - for (const secret of Object.values(secretStore)) { - stringified = stringified.replace(secret.from, secret.to); - } - return [key, JSON.parse(stringified)]; - }) - ); - }; - - const timeline: TimelineEntry[] = data.timeline.map((entry) => { - const [type, d] = entry; - if (type === "nodeend") { - const data = d as NodeEndResponse; - // "node" has a "?" only because when reading back loaded run, - // "node" doesn't exist here (addNodeend doesn't use it). - // TODO: make more elegant. - if (data.node?.type === "secrets") { - Object.entries(data.outputs).forEach(([key, value]) => { - if (secretStore[key]) return; - const from = value as string; - const to = replacer(key, from); - secretStore[key] = { from, to }; - }); - } - - return [ - "nodeend", - { - ...(d as object), - outputs: processPorts(data.outputs), - }, - ]; - } else if (type === "nodestart") { - return [ - "nodestart", - { - ...(d as object), - inputs: processPorts(d.inputs), - }, - ] as TimelineEntry; - } - return entry as TimelineEntry; - }); - - const secrets = serializeSecrets(); - - const result: SerializedRun = { - $schema: data.$schema, - version: data.version, - secrets, - timeline, - }; - if (data.data) { - result.data = data.data; - } - return result; -}; diff --git a/packages/breadboard/src/inspector/schemas.ts b/packages/breadboard/src/inspector/schemas.ts deleted file mode 100644 index abdfdae9860..00000000000 --- a/packages/breadboard/src/inspector/schemas.ts +++ /dev/null @@ -1,129 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { SchemaBuilder, combineSchemas } from "../schema.js"; -import { NodeDescriberResult, Schema } from "../types.js"; -import { - InspectableEdge, - InspectableEdgeType, - NodeTypeDescriberOptions, -} from "./types.js"; - -export enum EdgeType { - In, - Out, -} - -const SCHEMA_SCHEMA: Schema = { - type: "object", - title: "Schema", - behavior: ["json-schema", "ports-spec", "config"], -}; - -export const DEFAULT_SCHEMA: Schema = { type: "string" }; - -const blankSchema = () => ({ type: "object" }); - -const isStarOrControl = (edge: InspectableEdge) => { - const type = edge.type; - return ( - type === InspectableEdgeType.Star || type === InspectableEdgeType.Control - ); -}; - -const edgesToProperties = ( - edgeType: EdgeType, - edges?: InspectableEdge[], - keepStar = false -): Record => { - if (!edges) return {}; - return edges.reduce( - (acc, edge) => { - if (!keepStar && isStarOrControl(edge)) return acc; - const key = edgeType === EdgeType.In ? edge.in : edge.out; - if (acc[key]) return acc; - acc[key] = DEFAULT_SCHEMA; - return acc; - }, - {} as Record - ); -}; - -export const edgesToSchema = ( - edgeType: EdgeType, - edges?: InspectableEdge[], - keepStar = false -): Schema => { - if (!edges) return {}; - return new SchemaBuilder() - .addProperties(edgesToProperties(edgeType, edges, keepStar)) - .setAdditionalProperties(true) - .build(); -}; - -/** - * Constructs a Schema for an input node. - * @param options - * @returns - */ -export const describeInput = ( - options: NodeTypeDescriberOptions -): NodeDescriberResult => { - const schema = (options.inputs?.schema as Schema) || blankSchema(); - const inputSchema = new SchemaBuilder() - .addProperty("schema", SCHEMA_SCHEMA) - .build(); - let hasStarEdge = false; - const outgoing = options.outgoing?.filter((edge) => { - const isStarEdge = isStarOrControl(edge); - if (isStarEdge) { - hasStarEdge = true; - } - return !isStarEdge; - }); - const outputSchema = combineSchemas([ - edgesToSchema(EdgeType.Out, outgoing, true), - schema, - ]); - if (options.asType) { - if (!hasStarEdge) { - outputSchema.additionalProperties = false; - } - } - return { inputSchema, outputSchema }; -}; - -/** - * Constructs a Schema for an output node. - * @param options - * @returns - */ -export const describeOutput = ( - options: NodeTypeDescriberOptions -): NodeDescriberResult => { - const schema = (options.inputs?.schema as Schema) || blankSchema(); - const outputSchema = new SchemaBuilder() - .setAdditionalProperties(false) - .build(); - const inputSchemaBuilder = new SchemaBuilder().addProperty( - "schema", - SCHEMA_SCHEMA - ); - const inputSchema = combineSchemas([ - inputSchemaBuilder - .addProperties(edgesToProperties(EdgeType.In, options.incoming, true)) - .setAdditionalProperties(true) - .build(), - schema, - ]); - if (options.asType) { - // If the output has star edge incoming, make sure to communicate that - // this output can have many actual ports: set additionalProperties to true. - const hasStarEdge = !!options.incoming?.find((edge) => edge.out === "*"); - if (!hasStarEdge) inputSchema.additionalProperties = false; - } - return { inputSchema, outputSchema }; -}; diff --git a/packages/breadboard/src/inspector/types.ts b/packages/breadboard/src/inspector/types.ts deleted file mode 100644 index 6de6111ba44..00000000000 --- a/packages/breadboard/src/inspector/types.ts +++ /dev/null @@ -1,1058 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphIdentifier, - GraphMetadata, - NodeMetadata, - StartLabel, -} from "@google-labs/breadboard-schema/graph.js"; -import { HarnessRunResult, SecretResult } from "../harness/types.js"; -import { GraphLoader } from "../loader/types.js"; -import { - BehaviorSchema, - Edge, - EdgeResponse, - ErrorResponse, - GraphDescriptor, - InputValues, - Kit, - KitDescriptor, - NodeConfiguration, - NodeDescriberResult, - NodeDescriptor, - NodeHandlerMetadata, - NodeIdentifier, - NodeTypeIdentifier, - NodeValue, - OutputValues, - Schema, -} from "../types.js"; -import { - DataStore, - RunStore, - SerializedDataStoreGroup, -} from "../data/types.js"; -import { SequenceEntry } from "./run/serializer.js"; - -export type GraphVersion = number; - -export type GraphURL = string; - -/** - * Represents an UUID that is used to identify a graph. - */ -export type GraphUUID = `${GraphVersion}|${GraphURL}`; - -export type InspectableNode = { - /** - * The `NodeDescriptor` for the node. - */ - descriptor: NodeDescriptor; - /** - * The title of the node. Use this to get a consistent name for the node. - * When the node has a title in the `NodeMetadata`, will be used. - * Otherwise, the id of the node will be used. - */ - title(): string; - /** - * The description of the node as found in `NodeMetadata`. If not found, - * falls back to `title()`. - */ - description(): string; - /** - * Returns the nodes that have an edge to this node. - */ - incoming(): InspectableEdge[]; - /** - * Returns the nodes that have an edge from this node. - */ - outgoing(): InspectableEdge[]; - /** - * Return true if the node is an entry node (labeled as such or - * has no incoming edges) - */ - isEntry(label?: StartLabel): boolean; - /** - * The start label of the node. - */ - startLabels(): StartLabel[] | undefined; - /** - * Return true if the node is an exit node (no outgoing edges) - */ - isExit(): boolean; - /** - * Returns the `InspectableNodeType` instance for the node. - */ - type(): InspectableNodeType; - - /** - * Returns the API of the node. - * - * A note about the relationship between `describe`, `subgraph.describe`, - * and `incoming`/`outgoing`: - * - the `describe` returns the API as the node itself expects it - * - the `incoming` and `outgoing` return the actual wires going in/out - * - the `subgraph.describe` returns the API of the subgraph that the node - * contains (or represents). For instance, the `invoke` node has a `path` - * required property. This property will show up in `describe` (since it - * specifies the path of the graph), but not in `subgraph.describe` (since - * the subgraph itself doesn't actually use it). - * - * This function is designed to match the output of the - * `NodeDescriberFunction`. - */ - describe(inputs?: InputValues): Promise; - /** - * Returns configuration of the node. - * TODO: Use a friendlier to inspection return type. - */ - configuration(): NodeConfiguration; - /** - * Returns metadata for the node. - * TODO: Use a friendlier to inspection return type. - */ - metadata(): NodeMetadata; - /** - * Returns the current state of node's ports - */ - ports( - inputs?: InputValues, - outputs?: OutputValues - ): Promise; -}; - -/** - * The type of the edge. - */ -export enum InspectableEdgeType { - /** - * Just an ordinary edge. Most of the edges in graphs are ordinary. - */ - Ordinary = "ordinary", - /** - * Constant edge has an effect of "memoizing" the value that passes - * through it, make it always available. So when the incoming node is among - * opportunities to visit again, the constant edge will report that it already - * has the value. - * Each new value that comes from the outgoing wire will overwrite the one - * that is memoized. - * Constant edges are primarily useful when building graphs with cycles. - * For example, if you want to invoke some fetch multiple times, with the same - * secret value, use the constant edge to connect the secret to the fetch. - */ - Constant = "constant", - /** - * Control edge does not pass any data across. It is purely a control flow - * wire, primarily useful when building graphs with cycles. - */ - Control = "control", - /** - * Star edge is the opposite of control edge: it passes all data from outgoing - * node to incoming node. Use it when you do not need to discern what - * ports are being passed and their names match for the incoming/outgoing - * nodes. - */ - Star = "star", -} - -export type InspectableEdge = { - /** - * The outgoing node of the edge. - */ - from: InspectableNode; - /** - * The name of the port of the outgoing node. - */ - out: string; - /** - * The incoming node of the edge. - */ - to: InspectableNode; - /** - * The name of the port of the incoming node. - */ - in: string; - /** - * The type of the edge. - */ - type: InspectableEdgeType; - - /** - * Get an inspectable output port. - */ - outPort(): Promise; - - /** - * Get the inspectable input port. - */ - inPort(): Promise; - - /** - * Check if the input and output schemas are compatible (meaning that the - * output port type is a subtype of the input port type). - */ - validate(): Promise; -}; - -export type ValidateResult = - | { status: "unknown"; errors?: never } - | { status: "valid"; errors?: never } - | { status: "invalid"; errors: ValidateError[] }; - -export interface ValidateError { - message: string; - detail?: { - outputPath: Array; - inputPath: Array; - }; -} - -export type InspectableSubgraphs = Record; - -export type InspectableGraph = { - /** - * Returns the underlying `GraphDescriptor` object. - * TODO: Replace all uses of it with a proper inspector API. - */ - raw(): GraphDescriptor; - /** - * Returns this graph's metadata, if exists. - */ - metadata(): GraphMetadata | undefined; - /** - * Returns the node with the given id, or undefined if no such node exists. - * @param id id of the node to find - */ - nodeById(id: NodeIdentifier): InspectableNode | undefined; - /** - * Returns all nodes in the graph. - */ - nodes(): InspectableNode[]; - /** - * Returns all edges of the graph. - */ - edges(): InspectableEdge[]; - /** - * Returns true if the edge exists in the graph. - */ - hasEdge(edge: Edge): boolean; - /** - * Returns all kits in the graph. - */ - kits(): InspectableKit[]; - /** - * Returns all nodes of the given type. - * @param type type of the nodes to find - */ - nodesByType(type: NodeTypeIdentifier): InspectableNode[]; - /** - * Returns the `InspectableNodeType` for a given node or undefined if the - * node does not exist. - */ - typeForNode(id: NodeIdentifier): InspectableNodeType | undefined; - /** - * Returns the `InspectableNodeType` for a given type or undefined if the type - * does not exist. - */ - typeById(id: NodeTypeIdentifier): InspectableNodeType | undefined; - /** - * Describe a given type of the node - */ - describeType( - type: NodeTypeIdentifier, - options?: NodeTypeDescriberOptions - ): Promise; - /** - * Returns the nodes that have an edge to the node with the given id. - * @param id id of the node to find incoming nodes for - */ - incomingForNode(id: NodeIdentifier): InspectableEdge[]; - /** - * Returns the nodes that have an edge from the node with the given id. - * @param id id of the node to find outgoing nodes for - */ - outgoingForNode(id: NodeIdentifier): InspectableEdge[]; - /** - * Returns a list of entry nodes for the graph. - */ - entries(label?: StartLabel): InspectableNode[]; - /** - * Returns the API of the graph. This function is designed to match the - * output of the `NodeDescriberFunction`. - */ - describe(inputs?: InputValues): Promise; - /** - * Returns the subgraphs that are embedded in this graph. - */ - graphs(): InspectableSubgraphs; -}; - -/** - * Options to supply to the `inspectableGraph` function. - */ -export type InspectableGraphOptions = { - /** - * Optional, a list of kits to use when inspecting the graph. If not - * supplied, the graph will be inspected without any kits. - */ - kits?: Kit[]; - /** - * The loader to use when loading boards. - */ - loader?: GraphLoader; -}; - -/** - * Options to supply to the `describeType` function. - */ -export type NodeTypeDescriberOptions = { - /** - * Optional, the inputs to the node. - */ - inputs?: InputValues; - /** - * Optional, the incoming edges to the node. - */ - incoming?: InspectableEdge[]; - /** - * Optional, the outgoing edges from the node. - */ - outgoing?: InspectableEdge[]; - /** - * Optional, describe the the type for type description purposes, rather - * than for inspection. - */ - asType?: boolean; -}; - -/** - * Describes the current status of a node port. - */ -export enum PortStatus { - /** - * The port status impossible to determine. This only happens when the node - * has a star wire ("*") and the port is not connected. - */ - Indeterminate = "indeterminate", - /** - * The port is correctly connected to another node or specified using node's - * configuration, according to this node's schema. - */ - Connected = "connected", - /** - * The port is not connected to another node, and it is expected, but not - * required by the node's schema. - */ - Ready = "ready", - /** - * The port is not connected to another node, but it is required by the node's - * schema. It is similar to "Ready", except that not having this port - * connected is an error. - */ - Missing = "missing", - /** - * The port is connected to this node, but it is not expected by the node's - * schema. This is an error state. - */ - Dangling = "dangling", -} - -/** - * Describes a node port (input or output). - */ -export type InspectablePort = { - /** - * The name of the port. - */ - name: string; - /** - * The title of the port, if specified by schema. Otherwise, same as the - * name of the port - */ - title: string; - /** - * Returns current status of this port. - */ - status: PortStatus; - /** - * Returns true if the port was specified in the node's configuration. - */ - configured: boolean; - /** - * Returns current value for the port. This value is computed as follows: - * - if there is a value coming from one of the incoming edges, then - * return that value; - * - otherwise, if there is a value specified in node's configuration, - * then return that value; - * - otherwise, return null; - */ - value: NodeValue; - /** - * Returns true if this is the star or control port ("*" or ""). - */ - star: boolean; - /** - * Port schema as defined by the node's configuration. - */ - schema: Schema; - /** - * Returns the edges connected to this port. - */ - edges: InspectableEdge[]; - - /** - * Returns a representation of the port's type. - */ - type: InspectablePortType; - - /** - * Is this an input or output port? - */ - kind: "input" | "output"; -}; - -export type InspectablePortType = { - /** - * Returns port schema as defined by the node. - */ - schema: Schema; - /** - * Returns `true` if this port has specified behavior - */ - hasBehavior(behavior: BehaviorSchema): boolean; - /** - * Returns `true` if the outgoing port of this type can connect to an - * incoming port of the specified type. - * - * @param to the incoming port type to which to connect. - */ - canConnect(to: InspectablePortType): boolean; - - analyzeCanConnect(to: InspectablePortType): CanConnectAnalysis; -}; - -export type CanConnectAnalysis = - | { canConnect: true; details?: never } - | { canConnect: false; details: CanConnectAnalysisDetail[] }; - -export interface CanConnectAnalysisDetail { - message: string; - detail?: { - outputPath: Array; - inputPath: Array; - }; -} - -/** - * Represents one side (input or output) of ports of a node. - */ -export type InspectablePortList = { - /** - * Input ports of the node. - */ - ports: InspectablePort[]; - /** - * Returns true if the list of ports is fixed. Returns false if the node - * expects a dynamic number of ports. - * - * Fixed example: the `validateJson` node, which has two fixed input ports: - * `json` and `schema`. - * - * Conversely, the `core.invoke` node is an example of the dynamic number of - * ports, which can take any number of inputs and they are passed to the - * invoked graph as arguments. - */ - fixed: boolean; -}; - -/** - * Represents the input and output ports of a node. - */ -export type InspectableNodePorts = { - /** - * Returns the input ports of the node. - */ - inputs: InspectablePortList; - /** - * Returns the output ports of the node. - */ - outputs: InspectablePortList; -}; - -/** - * Represents a Breadboard Kit associated with the board. - */ -export type InspectableKit = { - /** - * Returns the descriptor of the kit. - */ - descriptor: KitDescriptor; - /** - * Returns the node types of the kit. - */ - nodeTypes: InspectableNodeType[]; -}; - -export type InspectableNodeType = { - /** - * Returns the metadata, associated with this node type. - */ - metadata(): Promise; - /** - * Returns the type of the node. - */ - type(): NodeTypeIdentifier; - /** - * Returns the ports of the node. - */ - ports(): Promise; -}; - -/** - * Represents a simple listener for edits to the graph. - * An instance of this type is returned by the `editReceiver` method of - * `InspectableGraph`. - */ -export type GraphStoreMutator = { - // TODO: This is probably wrong. A new version of the graph should likely - // create a new instance of an `InspectableGraph`. - updateGraph(graph: GraphDescriptor): void; - // Destroys all caches. - // TODO: Maybe too much machinery here? Just get a new instance of inspector? - resetGraph(graph: GraphDescriptor): void; - nodeStore: NodeStoreMutator; - edgeStore: EdgeStoreMutator; -}; - -export type NodeStoreMutator = { - add(node: NodeDescriptor): void; - remove(id: NodeIdentifier): void; -}; - -export type EdgeStoreMutator = { - add(edge: Edge): void; - remove(edge: Edge): void; -}; - -export type InspectableGraphWithStore = InspectableGraph & GraphStoreMutator; - -export type InspectableEdgeCache = { - get(edge: Edge): InspectableEdge | undefined; - getOrCreate(edge: Edge): InspectableEdge; - add(edge: Edge): void; - remove(edge: Edge): void; - hasByValue(edge: Edge): boolean; - edges(): InspectableEdge[]; -}; - -export type InspectableNodeCache = { - byType(type: NodeTypeIdentifier): InspectableNode[]; - get(id: string): InspectableNode | undefined; - add(node: NodeDescriptor): void; - remove(id: NodeIdentifier): void; - nodes(): InspectableNode[]; -}; - -/** - * A backing store for `InspectableGraph` instances, representing a stable - * instance of a graph whose properties mutate. - */ -export type MutableGraph = { - nodes: InspectableNodeCache; - edges: InspectableEdgeCache; -}; - -/** - * Represents a store of graph versions. - */ -export type InspectableGraphVersionsStore = { - /** - * Retrieves a graph with the given id, and optionally, version and run. - * @param id -- the id of the graph to retrieve - * @param version -- the version of the graph to retrieve (optional, - * defaults to 0) - * @param run -- the run of the graph to retrieve (optional, defaults to 0) - */ - get( - id: GraphUUID, - version?: number, - run?: number - ): Promise; -}; - -/** - * Represents a sequence of versions of a graph. - * This sequence of versions grows as the graph is edited. - */ -export type InspectableGraphVersions = { - /** - * The unique identifier of the sequence of graph versions. - */ - id: GraphUUID; - /** - * A list of versions for the given graph. Every edit to the graph - * results in a new version. The first item in the list is the initial - * version of the graph. The last item is the latest version. - */ - versions: InspectableVersionedGraph[]; - /** - * Returns only major versions of the graph. - * A "major" version of the graph is a version that has one or more runs - * associated with it. A "minor" version is a version that has no runs. - */ - major(): InspectableVersionedGraph[]; -}; - -/** - * Represents a versioned graph. - * A versioned graph has zero or more runs associated with it. - */ -export type InspectableVersionedGraph = { - /** - * The unique identifier of the versioned graph. This is a monotonically - * increasing number, starting from 0. Same as the index of the `versions` - * array in the `InspectableGraphWithVersions` object. - */ - id: number; - graph: InspectableGraph; - runs: InspectableRun[]; -}; - -/** - * Represents a result of loading a serialized `InspectableRun` - */ -export type InspectableRunLoadResult = - | { - success: false; - error: string; - } - | { - success: true; - run: InspectableRun; - }; - -/** - * Represents an observer of the graph runs. - */ -export type InspectableRunObserver = { - /** - * Returns the list of runs that were observed. The current run is always - * at the top of the list. - */ - runs(): Promise; - /** - * Observes the given result and collects it into the list of runs. - * @param result -- the result to observe - * @returns -- the list of runs that were observed - */ - observe(result: HarnessRunResult): Promise; - /** - * Attempts to load a JSON object as a serialized representation of runs, - * creating a new run if successful. - * @param o -- the object to load. Must be shaped as `SerializedRun`. - * @returns -- an `InspectableRunLoadResult` instance. - */ - load( - o: unknown, - options?: SerializedRunLoadingOptions - ): Promise; -}; - -/** - * Represents a function that replaces secrets. - * @param name -- the name of the secret - * @param value -- the current value of the secret - * @returns -- the new value of the secret - */ -export type SerializedRunSecretReplacer = ( - name: string, - value: string -) => string; - -/** - * Represents options to supply to the `load` method of `InspectableRunObserver`. - */ -export type SerializedRunLoadingOptions = { - /** - * Optional, a function replace sentinel values with actual secrets. - */ - secretReplacer?: SerializedRunSecretReplacer; - /** - * Optional, kits that are used with this run. - */ - kits?: Kit[]; -}; - -export type StoreAdditionResult = { - /** - * The UUID of the graph - */ - id: GraphUUID; - /** - * True, if the graph did not exist in the store before and was added as - * a result of this operation. - * False, if the graph already existed. - */ - added: boolean; -}; - -/** - * Represents a store of all graphs that the system has seen so far. - */ -export type GraphDescriptorStore = { - /** - * Retrieves a graph with the given id. - * @param id -- the id of the graph to retrieve - */ - get(id: GraphUUID): GraphDescriptor | undefined; - /** - * Checks if the store has a graph with the given id. - * @param id -- the id of the graph - */ - has(id: GraphUUID): boolean; - /** - * Adds a graph to the store and returns a `StoreAdditionResult`. - * @see StoreAdditionResult - */ - add(graph: GraphDescriptor, version: number): StoreAdditionResult; -}; - -/** - * Represents a pair of the nodestart and nodeend results that were generated - * during the run. - */ -export type InspectableRunNodeEvent = { - type: "node"; - /** - * Unique identifier of the event. - */ - id: EventIdentifier; - /** - * The graph that contains this node. - */ - graph: InspectableGraph; - /** - * The `InspectableNode` instance associated with this node. - */ - node: InspectableNode; - /** - * The timestamp of the `nodestart` event. - */ - start: number; - /** - * The timestamp of the `nodeend` event. Can be null when the `nodeend` has - * not been received yet. - */ - end: number | null; - /** - * The inputs that were provided to the node - */ - inputs: InputValues; - /** - * The outputs that were produced by the node. Can be null when the `nodeend` - * has not been received yet. - */ - outputs: OutputValues | null; - /** - * Returns true when the input or output node was bubbled up from a nested - * graph. This is only populated for the top-level graph. - */ - bubbled: boolean; - /** - * Returns true if the event should be hidden in the UI. - */ - hidden: boolean; - /** - * Returns the list of nested runs that were (or are being) create when - * this node was (is being) invoked. - */ - runs: InspectableRun[]; -}; - -/** - * Represents an error event that was generated during the run. - */ -export type InspectableRunErrorEvent = { - type: "error"; - id: EventIdentifier; - error: ErrorResponse["error"]; - /** - * When the error was first observed. - */ - start: number; -}; - -export type InspectableRunEdgeEvent = { - type: "edge"; - id: EventIdentifier; - edge: { - /** - * The outgoing node of the edge. - */ - from?: string; - /** - * The name of the port of the outgoing node. - */ - out?: string; - /** - * The incoming node of the edge. - */ - to?: string; - /** - * The name of the port of the incoming node. - */ - in?: string; - }; - start: number; - end: number; - from?: number[]; - to?: number[]; - value?: InputValues; -}; - -export type InspectableRunSecretEvent = { - type: "secret"; - id: EventIdentifier; - keys: SecretResult["data"]["keys"]; - /** - * When the `secrets` node was first observed. - */ - start: number; - /** - * When the `secrets` node was handled. - */ - end: number | null; -}; - -/** - * A unique identifier for an `InspectableRunEvent` instance. - */ -export type EventIdentifier = string; - -/** - * Values that were submitted as inputs during a run. - */ -export type InspectableRunInputs = Map; - -/** - * Represent all events that can be inspected during a run. - */ -export type InspectableRunEvent = - | InspectableRunNodeEvent - | InspectableRunSecretEvent - | InspectableRunErrorEvent - | InspectableRunEdgeEvent; - -export type InspectableRunEdge = EdgeResponse; - -/** - * Represents a single run of a graph. - */ -export type InspectableRun = { - /** - * The id of the graph that was run. - */ - graphId: GraphUUID; - /** - * The version of the graph that was run. - */ - graphVersion: number; - /** - * Start time of the run. - */ - start: number; - /** - * End time of the run. Can be null if the run has not finished yet. - */ - end: number | null; - /** - * All events within this graph that have occurred during the run. - * The nested graph events aren't included. - */ - events: InspectableRunEvent[]; - edges: InspectableRunEdge[]; - /** - * A way to associate data with the run. - */ - dataStoreKey: string; - /** - * Returns the current `InspectableRunNodeEvent` if any. - * This is useful for tracking the latest node that is being run. - * - * Note: this will return node events for nested runs as well as the - * top-level run. - */ - currentNodeEvent(): InspectableRunNodeEvent | null; - /** - * Returns the current run stack as a list of `InspectableRunNodeEvent` - * instances. - * The first item in the list represents the node in the top-level - * graph that is currently being run. - * The last item is the actual node that is being run, which may be in a - * graph that is nested within the top-level graph. - */ - stack(): InspectableRunNodeEvent[]; - /** - * If present, returns a serialized representation of the run or null if - * serialization of this run is not supported. - */ - serialize?(options?: RunSerializationOptions): Promise; - /** - * Given an `EventIdentifier`, returns an `InspectableRunEvent` instance or - * null if not found. - */ - getEventById(id: EventIdentifier): InspectableRunEvent | null; - /** - * Creates a map of all inputs that were submitted during the run or `null` - * if no inputs were submitted. - */ - inputs(): InspectableRunInputs | null; - /** - * Returns a HarnessRunResult asynchronous generator that allows replaying - * the run. - */ - replay(): AsyncGenerator; -}; - -/** - * Represents options to supply to the `serialize` method of `InspectableRun`. - */ -export type RunSerializationOptions = { - /** - * Optional, whether or not to elide secrets. When set to true, secrets - * are kept as is. When set to false or not present, secrets are elided and - * replaced with sentinel values. - */ - keepSecrets?: boolean; -}; - -export type SequenceView = { - sequence: SequenceEntry[]; - start: number; -}; - -export type PathRegistryEntry = { - path: number[]; - parent: PathRegistryEntry | null; - children: PathRegistryEntry[]; - graphId: GraphUUID | null; - graphStart: number; - graphEnd: number | null; - event: InspectableRunEvent | null; - view: SequenceView | null; - /** - * Sidecars are events that are displayed at a top-level, but aren't - * part of the main event list. Currently, sidecar events are: - * - Input events that have bubbled up. - * - Output events that have bubbled up. - * - Secret events. - * - Error events. - */ - sidecars: InspectableRunEvent[]; - /** - * Returns true if the entry has no children. - */ - empty(): boolean; - /** - * Returns nested events for this entry. - */ - events: InspectableRunEvent[]; - /** - * Returns the edges associated with this entry. - * These will be the various edges that were traveled when traversing - * the graph associated with this entry. - */ - edges: InspectableRunEdge[]; - /** - * Returns an inspectable graph for the graph, associated with this entry. - */ - graph: InspectableGraph | null; - - find(path: number[]): PathRegistryEntry | null; -}; - -export type RunObserverLogLevel = - /** - * Show only events that are marked as info. - * Typically, these are useful for communicating the - * broad picture of what the graph is doing. - */ - | "info" - /** - * Show info events and debug events. This includes all - * events that are emitted by the graph. - */ - | "debug"; - -export type RunObserverOptions = { - /** - * Logging level. - */ - logLevel?: RunObserverLogLevel; - /** - * The kits that are being used during this run. Used to provide - * the ability to inspect graphs and nodes during the run. - */ - kits?: Kit[]; - /** - * The data store that will manage non-text data within the run. - */ - dataStore?: DataStore; - /** - * The store that will be used to capture the run's data. - */ - runStore?: RunStore; - /** - * Whether or not to skip replacing inlineData parts with storedData parts. - */ - skipDataStore?: boolean; -}; - -export type GraphstartTimelineEntry = [ - type: "graphstart", - data: { - timestamp: number; - path: number[]; - index: number; - graph: GraphDescriptor | null; - edges: InspectableRunEdge[]; - }, -]; - -export type NodestartTimelineEntry = [ - type: "nodestart", - data: { - id: NodeIdentifier; - graph: number; - inputs: InputValues; - path: number[]; - timestamp: number; - }, -]; - -// TODO: Figure out if this is permanent. -export type TimelineEntry = - | [ - type: "graphend" | "input" | "output" | "secret" | "error" | "nodeend", - data: unknown, - ] - | GraphstartTimelineEntry - | NodestartTimelineEntry; - -/** - * Represents an `InspectableRun` that has been serialized into a JSON object. - * This object can be used to store the run in a file or send it over the wire. - * The serialized run can be deserialized back into an `InspectableRun` object - * using the `InspectableRunObserver.load` method. - */ -export type SerializedRun = { - $schema: "tbd"; - version: "0"; - secrets?: Record; - timeline: TimelineEntry[]; - data?: SerializedDataStoreGroup; -}; diff --git a/packages/breadboard/src/kits/builder.ts b/packages/breadboard/src/kits/builder.ts deleted file mode 100644 index ca8ff9c4f5c..00000000000 --- a/packages/breadboard/src/kits/builder.ts +++ /dev/null @@ -1,202 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { KitDescriptor, KitTag } from "@google-labs/breadboard-schema/graph.js"; -import { - ConfigOrGraph, - GenericKit, - InputValues, - Kit, - KitConstructor, - NodeFactory, - NodeHandler, - NodeHandlers, -} from "../types.js"; - -export type KitBuilderOptions = KitDescriptor & { - namespacePrefix?: string; -}; - -/* eslint-disable @typescript-eslint/no-explicit-any */ -type FunctionsKeysOnly = { - [P in keyof T]: T[P] extends (...args: any[]) => void ? P : never; -}[keyof T]; -type FunctionsOnly = Pick>; - -export class KitBuilder { - url: string; - title?: string; - description?: string; - version?: string; - namespacePrefix?: string; - tags: KitTag[]; - - constructor({ - title, - description, - version, - url, - namespacePrefix = "", - tags = [], - }: KitBuilderOptions) { - this.url = url; - this.title = title; - this.description = description; - this.version = version; - this.namespacePrefix = namespacePrefix; - this.tags = tags; - } - - #addPrefix(handlers: NodeHandlers) { - return Object.keys(handlers).reduce((acc, key) => { - acc[`${this.namespacePrefix}${key}`] = handlers[key]; - return acc; - }, {} as NodeHandlers); - } - - build(handlers: Handlers) { - type NodeNames = [x: Extract]; - - if (!this.url) throw new Error(`Builder was not yet initialized.`); - const url = this.url; - const prefix = this.namespacePrefix; - const { title, description, version, tags } = this; - - const prefixedHandlers = this.#addPrefix(handlers); - - const nodes = Object.keys(handlers); - - return class implements Kit { - title = title; - description = description; - version = version; - url = url; - tags = tags; - - get handlers() { - return prefixedHandlers; - } - - constructor(nodeFactory: NodeFactory) { - const proxy = new Proxy(this, { - get(target, prop: string) { - if ( - prop === "handlers" || - prop === "url" || - prop === "title" || - prop === "tags" - ) { - return target[prop]; - } else if (nodes.includes(prop as NodeNames[number])) { - return (configOrGraph: ConfigOrGraph = {}) => { - const config = nodeFactory.getConfigWithLambda(configOrGraph); - const { $id, ...rest } = config; - return nodeFactory.create( - proxy as unknown as Kit, - `${prefix}${prop}`, - { ...rest }, - $id - ); - }; - } - }, - }); - return proxy; - } - } as KitConstructor>; - } - - // eslint-disable-next-line @typescript-eslint/ban-types - static wrap>( - params: KitBuilderOptions, - functions: F - ): KitConstructor< - GenericKit<{ [x in keyof FunctionsOnly]: NodeHandler }> - > { - const createHandler = ( - previous: NodeHandlers, - // eslint-disable-next-line @typescript-eslint/ban-types - current: [string, Function] - ) => { - const [name, fn] = current; - - previous[name] = { - invoke: async (inputs: InputValues) => { - // JS can have rest args, eg. "...args" as a parameter at the end of a function, but breadboard cannot accept "." so we use "___". - - let argNames: string[] = []; - if (fn && fn.length > 0) { - argNames = - fn - .toString() - .match(/\((.+?)\)/)?.[1] - .split(",") ?? []; - - /* - If fn.length is greater than 1 and argNames.length = 0, then we likely have a system function that accepts a splat of arguments.. - - e.g Math.max([1,2,3,4]) - - We need to special case this and pass the arguments as an array and expect `inputs` to have a key of `args` that is an array. - */ - - if ( - fn.length > 1 && - argNames.length === 0 && - "___args" in inputs && - Array.isArray(inputs["___args"]) - ) { - argNames = ["___args"]; - } - } - - // Validate the input names. - for (const argName of argNames) { - if (argName.trim() in inputs === false) { - throw new Error( - `Missing input: ${argName.trim()}. Valid inputs are: ${Object.keys( - inputs - ).join(", ")}` - ); - } - } - - const args = argNames - .filter((argName) => argName.startsWith("___") == false) - .map((argName: string) => inputs[argName.trim()]); - - const lastArgName = argNames[argNames.length - 1]; - if (lastArgName != undefined && lastArgName.startsWith("___")) { - // Splat the rest of the arguments. - args.push(...(>inputs[lastArgName])); - } - - const results = await fn(...args); - - if (typeof results !== "object" || Array.isArray(results)) { - // Number, Boolean, Array, String, will output to `result`. - return { result: results }; - } - - // Objects will destructured into the output. - return { ...results }; - }, - }; - return previous; - }; - - const handlers = Object.entries(functions).reduce( - createHandler, - {} - ); - - const builder = new KitBuilder(params); - - return builder.build(handlers) as KitConstructor< - GenericKit<{ [x in keyof FunctionsOnly]: NodeHandler }> - >; - } -} diff --git a/packages/breadboard/src/kits/ctors.ts b/packages/breadboard/src/kits/ctors.ts deleted file mode 100644 index 823039730d4..00000000000 --- a/packages/breadboard/src/kits/ctors.ts +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - Breadboard, - BreadboardCapability, - ConfigOrGraph, - GraphDescriptor, - GraphDescriptorBoardCapability, - Kit, - KitConstructor, - NodeFactory, - OptionalIdConfiguration, -} from "../types.js"; -import { Node } from "../node.js"; - -/** - * Takes a kit constructor and creates a kit instance that can be used at - * run-time. - * - * @param ctor Kit constructor - * @returns A kit instance prepare for run-time use. - */ -export const asRuntimeKit = (ctor: KitConstructor) => { - return new ctor({ - create: () => { - throw Error("Node instantiation can't (yet) happen during runtime"); - }, - } as unknown as NodeFactory); -}; - -/** - * Takes a kit constructor and creates a kit instance that can be used at - * compose-time (wiring the graph). - * @param ctor Kit constructor - * @param board The board with which the kit is associated. - * @returns Kit instance prepared for compose-time use. - */ -export const asComposeTimeKit = ( - ctor: KitConstructor, - board: Breadboard -): Kit => { - return new ctor({ - create: (...args) => { - return new Node(board, ...args); - }, - getConfigWithLambda: (config: ConfigOrGraph): OptionalIdConfiguration => { - return getConfigWithLambda(board, config); - }, - }); -}; - -/** - * Syntactic sugar for node factories that accept lambdas. This allows passing - * either - * - A JS function that is a lambda function defining the board - * - A board capability, i.e. the result of calling lambda() - * - A board node, which should be a node with a `board` output - * or - * - A regular config, with a `board` property with any of the above. - * - * @param config {ConfigOrGraph} the overloaded config - * @returns {NodeConfigurationConstructor} config with a board property - */ -const getConfigWithLambda = ( - board: Breadboard, - config: ConfigOrGraph -): OptionalIdConfiguration => { - // Did we get a graph? - const gotGraph = - (config as GraphDescriptor).nodes !== undefined && - (config as GraphDescriptor).edges !== undefined && - (config as GraphDescriptor).kits !== undefined; - - // Look for functions, nodes and board capabilities. - const gotBoard = - gotGraph || - typeof config === "function" || - config instanceof Node || - ((config as BreadboardCapability).kind === "board" && - (config as GraphDescriptorBoardCapability).board); - - const result = ( - gotBoard - ? { board: gotGraph ? { kind: "board", board: config } : config } - : config - ) as OptionalIdConfiguration; - - return result; -}; diff --git a/packages/breadboard/src/kits/graph-to-kit.ts b/packages/breadboard/src/kits/graph-to-kit.ts deleted file mode 100644 index 7356dcce4e7..00000000000 --- a/packages/breadboard/src/kits/graph-to-kit.ts +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { callHandler, handlersFromKits } from "../handler.js"; -import { KitBuilderOptions } from "./builder.js"; -import { - GraphDescriptor, - InputValues, - Kit, - NodeDescriberResult, - NodeHandler, - NodeHandlerContext, - NodeHandlers, - NodeIdentifier, -} from "../types.js"; -import { inspect } from "../index.js"; - -export class GraphToKitAdapter { - graph: GraphDescriptor; - handlers?: NodeHandlers; - - private constructor(graph: GraphDescriptor) { - this.graph = graph; - } - - populateDescriptor(descriptor: KitBuilderOptions) { - const { title, description, version } = this.graph; - return { title, description, version, ...descriptor }; - } - - async #initialize(url: string, kits: Kit[] = []) { - this.graph.url = url; - // NOTE: This means that this board will _not_ use handlers defined upstream - // in the stack of boards to execute to nodes on this graph, but only the - // kits defined on this graph. - // - // Note however that `invoke` nodes will execute subgraphs with handlers - // from higher in the stack, so for example a subgraph defined here that - // uses `fetch` will use the `fetch` handler from the parent graph before - // using the `fetch` handler from kit defined here. - // - // The comment above applies only to nodes acting as node handler. We - // haven't seen this use-case yet for anything that isn't a Core node, so - // let's revisit once we have that. - this.handlers = kits?.reduce((acc, kit) => { - return { ...acc, ...kit.handlers }; - }, {} as NodeHandlers); - } - - handlerForNode(id: NodeIdentifier): NodeHandler { - if (!this.graph) throw new Error(`Builder was not yet initialized.`); - const { nodes } = this.graph; - const node = nodes.find((node) => node.id === id); - if (!node) throw new Error(`Node ${id} not found in graph.`); - - return { - metadata: node.configuration?.$metadata, - describe: async (): Promise => { - const emptyResult: NodeDescriberResult = { - inputSchema: { type: "object" }, - outputSchema: { type: "object" }, - }; - - if (this.graph.graphs != undefined && id in this.graph.graphs) { - const subGraph = this.graph.graphs[id] as GraphDescriptor; - if (subGraph == undefined) return emptyResult; - return await inspect(subGraph).describe(); - } else if (node.type === "invoke") { - const { $board } = node.configuration as { $board?: GraphDescriptor }; - if ($board) { - return await inspect($board).describe(); - } - } - - return emptyResult; - }, - invoke: async (inputs: InputValues, context: NodeHandlerContext) => { - const configuration = node.configuration; - if (configuration) { - inputs = { ...configuration, ...inputs }; - } - const handlers = { - ...this.handlers, - ...handlersFromKits(context?.kits || []), - }; - const handler = handlers?.[node.type]; - if (!handler) - throw new Error(`No handler found for node "${node.type}".`); - - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const board = this.graph; - - const base = board.url ? new URL(board.url) : new URL(import.meta.url); - - return callHandler(handler, inputs, { - ...context, - outerGraph: board, - base, - }); - }, - } as NodeHandler; - } - - static async create(graph: GraphDescriptor, url: string, kits: Kit[]) { - const adapter = new GraphToKitAdapter(graph); - await adapter.#initialize(url, kits); - return adapter; - } -} diff --git a/packages/breadboard/src/kits/index.ts b/packages/breadboard/src/kits/index.ts deleted file mode 100644 index e83678fe5c1..00000000000 --- a/packages/breadboard/src/kits/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export { SchemaBuilder } from "../schema.js"; -export { GraphToKitAdapter } from "./graph-to-kit.js"; -export { KitBuilder, type KitBuilderOptions } from "./builder.js"; -export { load, fromManifest } from "./load.js"; diff --git a/packages/breadboard/src/kits/load.ts b/packages/breadboard/src/kits/load.ts deleted file mode 100644 index 465ef9194b5..00000000000 --- a/packages/breadboard/src/kits/load.ts +++ /dev/null @@ -1,141 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { inspect } from "../inspector/index.js"; -import { loadWithFetch } from "../loader/default.js"; -import { invokeGraph } from "../run/invoke-graph.js"; -import { - GraphDescriptor, - InputValues, - Kit, - KitManifest, - NodeDescriberContext, - NodeHandlerContext, - NodeHandlerMetadata, - NodeHandlerObject, - Schema, -} from "../types.js"; -import { asRuntimeKit } from "./ctors.js"; - -const setBaseURL = (base: URL, key: string, graph: GraphDescriptor) => { - if (graph.edges && graph.nodes) { - const url = new URL(base); - url.searchParams.set("graph", key); - return { ...graph, url: url.href }; - } else { - throw new Error("Invalid graph descriptor"); - } -}; - -class GraphDescriptorNodeHandler implements NodeHandlerObject { - #base: URL; - #type: string; - #graph: GraphDescriptor; - metadata: NodeHandlerMetadata; - - constructor(base: URL, type: string, graph: GraphDescriptor) { - this.#base = base; - this.#type = type; - this.#graph = setBaseURL(base, type, graph); - this.describe = this.describe.bind(this); - this.invoke = this.invoke.bind(this); - const { title, description, metadata } = this.#graph; - this.metadata = { title, description }; - if (metadata?.deprecated) - this.metadata.deprecated = metadata.deprecated as boolean; - if (metadata?.icon) this.metadata.icon = metadata.icon; - if (metadata?.help) this.metadata.help = metadata.help; - if (metadata?.tags) this.metadata.tags = metadata.tags; - } - - async describe( - inputs?: InputValues, - _inputSchema?: Schema, - _outputSchema?: Schema, - context?: NodeDescriberContext - ) { - return await inspect(this.#graph, { - kits: context?.kits, - loader: context?.loader, - }).describe(inputs); - } - - async invoke(inputs: InputValues, context: NodeHandlerContext) { - return await invokeGraph(this.#graph, inputs, context); - } -} - -const createHandlersFromManifest = (base: URL, nodes: KitManifest["nodes"]) => { - return Object.fromEntries( - Object.entries(nodes).map(([key, value]) => { - return [key, new GraphDescriptorNodeHandler(base, key, value)]; - }) - ); -}; - -/** - * Creates a runtime kit from manifest. - * @param manifest -- a `KitManifest` instance - */ -export const fromManifest = (manifest: KitManifest): Kit => { - const { title, description, version, url } = manifest; - return { - title, - description, - version, - url, - handlers: createHandlersFromManifest(new URL(url), manifest.nodes), - }; -}; - -const isKitManifest = (obj: unknown): obj is KitManifest => { - if (typeof obj !== "object" || obj === null) return false; - const manifest = obj as KitManifest; - return ( - typeof manifest.title === "string" && - typeof manifest.description === "string" && - typeof manifest.version === "string" && - typeof manifest.url === "string" && - typeof manifest.nodes === "object" - ); -}; - -/** - * Loads a kit from a URL. - * - * @param url -- a URL to a kit manifest or an npm URL. - */ -export const load = async (url: URL): Promise => { - if (url.protocol === "https:" || url.protocol === "http:") { - if (url.pathname.endsWith(".kit.json")) { - const maybeManifest = await loadWithFetch(url); - if (isKitManifest(maybeManifest)) { - return fromManifest(maybeManifest); - } - } else { - // Assume that this is a URL to a JS file. - const module = await import(/* @vite-ignore */ url.href); - if (module.default == undefined) { - throw new Error(`Module ${url} does not have a default export.`); - } - - const moduleKeys = Object.getOwnPropertyNames(module.default.prototype); - - if ( - moduleKeys.includes("constructor") == false || - moduleKeys.includes("handlers") == false - ) { - throw new Error( - `Module default export '${url}' does not look like a Kit (either no constructor or no handler).` - ); - } - return asRuntimeKit(module.default); - } - } else if (url.protocol === "file:") { - throw new Error("File protocol is not yet supported"); - } - throw new Error(`Unable to load kit from "${url}"`); -}; diff --git a/packages/breadboard/src/loader/default.ts b/packages/breadboard/src/loader/default.ts deleted file mode 100644 index 3b71c15d944..00000000000 --- a/packages/breadboard/src/loader/default.ts +++ /dev/null @@ -1,163 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; -import { - GraphProvider, - GraphProviderCapabilities, - GraphProviderExtendedCapabilities, - GraphProviderStore, -} from "./types.js"; - -export const loadFromFile = async (path: string) => { - if (typeof globalThis.process === "undefined") - throw new Error("Unable to use `path` when not running in node"); - let readFileFn; - // The CJS transpilation process for node/vscode seems to miss this import, - // and leaves it as an import statement rather than converting it to a - // require. We therefore need a runtime check that prefers `require` if it - // is available. - if (typeof require === "function") { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const { readFile } = require("node:fs/promises"); - readFileFn = readFile; - } else { - const { readFile } = await import(/* vite-ignore */ "node:fs/promises"); - readFileFn = readFile; - } - - return JSON.parse(await readFileFn(path, "utf-8")); -}; - -export const loadWithFetch = async (url: string | URL) => { - let response; - try { - response = await fetch(url); - } catch (e) { - // Try again with credentials. - // This is useful for sites that require authentication. - // We also don't want this to be the default behavior, because some sites - // like Github have * CORS headers, which will make this request fail. - // See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials - response = await fetch(url, { credentials: "include" }); - } - return await response?.json(); -}; - -export class DefaultGraphProvider implements GraphProvider { - name = "DefaultGraphProvider"; - - #ready = Promise.resolve(); - ready() { - return this.#ready; - } - - isSupported(): boolean { - return true; - } - - extendedCapabilities(): GraphProviderExtendedCapabilities { - return { - modify: false, - connect: false, - disconnect: false, - refresh: false, - watch: false, - preview: false, - }; - } - - canProvide(url: URL): false | GraphProviderCapabilities { - if (url.protocol === "http:" || url.protocol === "https:") { - return { - load: true, - save: false, - delete: false, - }; - } - if (url.protocol === "file:" && url.hostname === "") { - return { - load: true, - save: false, - delete: false, - }; - } - return false; - } - - async load(url: URL): Promise { - if (url.protocol === "file:") { - const path = decodeURIComponent(url.pathname); - return loadFromFile(path); - } - if (url.protocol === "http:" || url.protocol === "https:") { - return loadWithFetch(url.href); - } - return null; - } - - async save( - _url: URL, - _descriptor: GraphDescriptor - ): Promise<{ result: boolean; error?: string }> { - throw new Error("Save not implemented for DefaultGraphProvider"); - } - - async delete(_url: URL): Promise<{ result: boolean; error?: string }> { - throw new Error("Delete not implemented for DefaultGraphProvider"); - } - - async connect(_location?: string): Promise { - throw new Error("Connect not implemented for DefaultGraphProvider"); - } - - async disconnect(_location: string): Promise { - throw new Error("Disconnect not implemented for DefaultGraphProvider"); - } - - async refresh(_location: string): Promise { - throw new Error("Refresh not implemented for DefaultGraphProvider"); - } - - async createBlank(_url: URL): Promise<{ result: boolean; error?: string }> { - throw new Error("Create Blank not implemented for DefaultGraphProvider"); - } - - async preview(_url: URL): Promise { - throw new Error("Create Blank not implemented for DefaultGraphProvider"); - } - - async create( - _url: URL, - _descriptor: GraphDescriptor - ): Promise<{ result: boolean; error?: string }> { - throw new Error("Create not implemented for DefaultGraphProvider"); - } - - async createURL(_location: string, _fileName: string): Promise { - throw new Error("createURL not implemented for DefaultGraphProvider"); - } - - parseURL(_url: URL): { location: string; fileName: string } { - throw new Error("parseURL not implemented for DefaultGraphProvider"); - } - - async restore() { - throw new Error("restore is not implemented for DefaultGraphProvider"); - } - - items(): Map { - throw new Error("items is not implemented for DefaultGraphProvider"); - } - - startingURL(): URL | null { - return null; - } - - watch(): void { - throw new Error("watch is not implemented for DefaultGraphProvider"); - } -} diff --git a/packages/breadboard/src/loader/index.ts b/packages/breadboard/src/loader/index.ts deleted file mode 100644 index b638b43c398..00000000000 --- a/packages/breadboard/src/loader/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Loader } from "./loader.js"; -import { GraphLoader, GraphProvider } from "./types.js"; -import { DefaultGraphProvider } from "./default.js"; - -export const createLoader = (graphProviders?: GraphProvider[]): GraphLoader => { - const providers = [...(graphProviders ?? []), new DefaultGraphProvider()]; - return new Loader(providers); -}; - -export { SENTINEL_BASE_URL } from "./loader.js"; diff --git a/packages/breadboard/src/loader/loader.ts b/packages/breadboard/src/loader/loader.ts deleted file mode 100644 index bffae6f54e1..00000000000 --- a/packages/breadboard/src/loader/loader.ts +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { GraphDescriptor, SubGraphs } from "../types.js"; -import type { - GraphProvider, - GraphLoader, - GraphLoaderContext, -} from "./types.js"; - -export const SENTINEL_BASE_URL = new URL("sentinel://sentinel/sentinel"); - -export const removeHash = (url: URL): URL => { - const newURL = new URL(url.href); - newURL.hash = ""; - return newURL; -}; - -export const sameWithoutHash = (a: URL, b: URL): boolean => { - return removeHash(a).href === removeHash(b).href; -}; - -export const baseURLFromContext = (context: GraphLoaderContext) => { - if (context.outerGraph?.url) return new URL(context.outerGraph.url); - const invokingBoardURL = context.board?.url; - if (invokingBoardURL) return new URL(invokingBoardURL); - if (context.base) return context.base; - return SENTINEL_BASE_URL; -}; - -export class Loader implements GraphLoader { - #graphProviders: GraphProvider[]; - - constructor(graphProviders: GraphProvider[]) { - this.#graphProviders = graphProviders; - } - - async #loadWithProviders(url: URL): Promise { - for (const provider of this.#graphProviders) { - const capabilities = provider.canProvide(url); - if (capabilities === false) { - continue; - } - if (capabilities.load) { - const graph = await provider.load(url); - if (graph !== null) { - // TODO: Remove this on 2024/9/1. By then, surely all of the graphs - // would have migrated to use the new name. - graph.nodes?.map((node) => { - if (node.type === "superWorker") { - console.warn("superWorker encountered, converting to specialist"); - node.type = "specialist"; - } - }); - graph.url = url.href; - return graph; - } - } - } - console.warn(`Unable to load graph from "${url.href}"`); - return null; - } - - async #loadOrWarn(url: URL): Promise { - const graph = await this.#loadWithProviders(url); - if (!graph) { - return null; - } - return graph; - } - - #getSubgraph( - url: URL | null, - hash: string, - subgraphs?: SubGraphs - ): GraphDescriptor | null { - if (!subgraphs) { - console.warn(`No subgraphs to load "#${hash}" from`); - return null; - } - const graph = subgraphs[hash]; - if (!graph) { - console.warn(`No subgraph found for hash: #${hash}`); - return null; - } - if (url) graph.url = url.href; - return graph; - } - - async load( - path: string, - context: GraphLoaderContext - ): Promise { - const supergraph = context.outerGraph; - // This is a special case, when we don't have URLs to resolve against. - // We are a hash path, and we are inside of a supergraph that doesn't - // have its own URL. We can only query the supergraph directly. - // No other URL resolution is possible. - const isEphemeralSupergraph = - path.startsWith("#") && supergraph && !supergraph.url; - if (isEphemeralSupergraph) { - const graph = this.#getSubgraph( - null, - path.substring(1), - supergraph.graphs - ); - if (!graph) { - console.warn(`Unable to load graph from "${path}"`); - } - return graph; - } - - const base = baseURLFromContext(context); - - const url = new URL(path, base); - - // If we don't have a hash, just load the graph. - if (!url.hash) { - return await this.#loadOrWarn(url); - } - - // Check to see if we match a special case: - // We are inside of a supergraph (a graph that contains us), _and_ we - // are trying to load a peer subgraph. - // In this case, do not trigger a load, but instead return the subgraph. - if (supergraph) { - const supergraphURL = supergraph.url - ? new URL(supergraph.url) - : SENTINEL_BASE_URL; - if (sameWithoutHash(url, supergraphURL)) { - const hash = url.hash.substring(1); - return this.#getSubgraph(url, hash, supergraph.graphs); - } - } - // Otherwise, load the graph and then get its subgraph. - const loadedSupergraph = await this.#loadOrWarn(removeHash(url)); - if (!loadedSupergraph) { - return null; - } - return this.#getSubgraph( - url, - url.hash.substring(1), - loadedSupergraph.graphs - ); - } -} diff --git a/packages/breadboard/src/loader/types.ts b/packages/breadboard/src/loader/types.ts deleted file mode 100644 index 548f351f8d8..00000000000 --- a/packages/breadboard/src/loader/types.ts +++ /dev/null @@ -1,360 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphDescriptor, - GraphTag, - NodeConfiguration, - NodeIdentifier, -} from "@google-labs/breadboard-schema/graph.js"; -import { Kit } from "../types.js"; - -export type GraphProviderItem = { - url: string; - username?: string; - title?: string; - tags?: GraphTag[]; - mine: boolean; - readonly: boolean; - handle: unknown; -}; - -export type GraphProviderStore = { - permission: "unknown" | "prompt" | "granted"; - title: string; - items: Map; -}; - -export type GraphProviderChange = { - type: "change" | "rename"; - previous: string | null; - filename: string; -}; - -export type ChangeNotificationCallback = ( - notification: GraphProviderChange -) => void; - -/** - * Describes the capabilities of a `GraphProvider` instance. - */ -export type GraphProviderCapabilities = { - /** - * Whether the provider can load graphs from the given URL. - */ - load: boolean; - /** - * Whether the provider can save graphs to the given URL. - */ - save: boolean; - /** - * Whether the provider can delete graphs at the given URL. - */ - delete: boolean; -}; - -export type GraphProviderExtendedCapabilities = { - /** - * Whether the provider can create, edit, and delete graphs. - */ - modify: boolean; - /** - * Whether the provider can be connected. - */ - connect: boolean; - /** - * Whether the provider can be disconnected. - */ - disconnect: boolean; - /** - * Whether the provider supports refreshing. - */ - refresh: boolean; - /** - * Whether the provider supports watching for change notifications. - */ - watch: boolean; - /** - * Whether the provider supports a preview URL. - */ - preview: boolean; -}; - -/** - * Represents a provider of `GraphDescriptor` instances. This is an - * extensibility point for Breadboard: you can add new providers to load - * graphs from different sources. - */ -export type GraphProvider = { - /** - * The name of the provider. - */ - name: string; - /** - * An indicator that the Provider is ready to serve graphs. - */ - ready(): Promise; - /** - * Whether the provider is supported or not in the current environment. - */ - isSupported(): boolean; - /** - * Given a URL, returns `false` if the provider cannot provide a graph for - * that URL, or a `GraphProviderCapabilities` object if it can. - * @param url -- the URL to check. - */ - canProvide(url: URL): false | GraphProviderCapabilities; - /** - * Expresses the `GraphProviderExtendedCapabilities` of the provider. - */ - extendedCapabilities(): GraphProviderExtendedCapabilities; - /** - * Given a URL, loads a `GraphDescriptor` instance from that URL. May - * return `null` if the graph could not be loaded. - * @param url -- the URL to load. - * @returns -- the loaded graph, or `null` if it could not be loaded. - */ - load: (url: URL) => Promise; - /** - * Given a URL, saves a `GraphDescriptor` instance to that URL. - * @param url -- the URL to save. - * @param descriptor -- the Graph Descriptor to save. - * @returns -- the result of saving, with an error if saving failed. - */ - save: ( - url: URL, - descriptor: GraphDescriptor - ) => Promise<{ result: boolean; error?: string }>; - /** - * Creates a blank board at the given URL - * @param url -- the URL at which to create the blank board - * @returns -- the result of creating the board, with an error if failed. - */ - createBlank(url: URL): Promise<{ result: boolean; error?: string }>; - /** - * Creates a board at the given URL - * @param url -- the URL at which to create the blank board - * @param graph -- the descriptor to use - * @returns -- the result of creating the board, with an error if failed. - */ - create( - url: URL, - graph: GraphDescriptor - ): Promise<{ result: boolean; error?: string }>; - /** - * Given a URL, deletes a `GraphDescriptor` instance at that URL. - * @param url -- the URL to delete - * @returns -- the result of deleting, with an error if saving failed. - */ - delete: (url: URL) => Promise<{ result: boolean; error?: string }>; - /** - * Connects to a given location if the Provider supports it. - * @param location -- if supported, the location to connect to. - * @param auth -- if supported, the authentication material to use. - * @returns -- nothing, but throws if connection fails. - */ - connect: (location?: string, auth?: unknown) => Promise; - /** - * Disconnects to a given location if the Provider supports it. - * @param url -- the location to save. - * @returns -- nothing, but throws if disconnection fails. - */ - disconnect: (location: string) => Promise; - /** - * Refreshes a given location if the Provider supports it. - * @param url -- the location to refresh. - * @returns -- nothing, but throws if refreshing fails. - */ - refresh: (location: string) => Promise; - /** - * Creates a provider-specific URL for a board. - * @param location -- the location of the board. - * @param fileName -- the board file path. - * @returns -- the provider-specific URL as a string or null when the URL can't be created. - */ - createURL: (location: string, fileName: string) => Promise; - /** - * Parses a provider-specific URL for a board. - * @param url -- the location of the board. - * @returns -- the location and file name of the board. - */ - parseURL: (url: URL) => { location: string; fileName: string }; - /** - * Signals to the provider to restore its state. For example, - * this is called when initializing UI to tell the store to load some - * previously-serialized state. - * @returns - */ - restore: () => Promise; - /** - * Provides a map of locations and their respective stores (lists of files) - * that can be used to enumerate all items that the provider can provide. - */ - items: () => Map; - /** - * Provides a starting URL for this store. - * Useful when we want to pick something to start a session with. - * Can be null if the store doesn't supply a starting URL. - */ - startingURL: () => URL | null; - /** - * Given the URL of a board, returns the URL of the node proxy server, if - * this provider supports it. If it doesn't, returns `false`. - */ - canProxy?: (url: URL) => Promise; - /** - * Provides a way to watch for changes in the store. - */ - watch: (callback: ChangeNotificationCallback) => void; - /** - * Provides a way to watch for changes in the store. - */ - preview: (url: URL) => Promise; -}; - -/** - * Describes the context in which a graph is being loaded. - * It's a subset of the `NodeHandlerContext` type. - * @see [NodeHandlerContext] - * - */ -export type GraphLoaderContext = { - /** - * The base URL for the graph being loaded. This may be a URL of the graph - * that is loading the graph, or it may be the URL of a graph higher in - * the graph hierarchy, since some graphs may be ephemeral: created without - * a URL. - */ - base?: URL; - /** - * The board that is loading this graph. - */ - board?: GraphDescriptor; - /** - * The graph that contains the graph being loaded. Usually the same as - * `board`, but may be different in some cases. - * TODO: Figure out what those cases are. - */ - outerGraph?: GraphDescriptor; -}; - -/** - * Represents a loader for `GraphDescriptor` instances. This is the main - * interface for loading graphs in Breadboard. - */ -export type GraphLoader = { - /** - * Loads a `GraphDescriptor` instance from a given path. May return `null`. - * @param path -- the path to load - * @param context -- the context in which to load the graph - * @returns -- the loaded graph, or `null` if it could not be loaded. - */ - load: ( - path: string, - context: GraphLoaderContext - ) => Promise; -}; - -/** - * Board Server Types - */ -export type Username = string; -export type UserApiKey = string; - -export interface BoardServerCapabilities { - connect: boolean; - disconnect: boolean; - refresh: boolean; - watch: boolean; - preview: boolean; -} - -export interface BoardServerConfiguration { - url: URL; - projects: Promise; - kits: Kit[]; - users: User[]; - secrets: Secrets; - extensions: BoardServerExtension[]; - capabilities: BoardServerCapabilities; -} - -export interface BoardServer extends GraphProvider, BoardServerConfiguration { - user: User; - getAccess(url: URL, user: User): Promise; -} - -export interface EntityMetadata { - owner: Username; - access: Map; - title?: string; - description?: string; - icon?: string; - tags?: GraphTag[]; -} - -export interface Entity { - url: URL; - metadata: EntityMetadata; -} - -export interface HostAPI { - send(method: string, args: unknown[]): Promise; -} - -export interface BoardServerExtension extends Entity { - node: { - onEditStart( - api: HostAPI, - id: NodeIdentifier, - type: string, - configuration: NodeConfiguration - ): Promise; - }; - graph: { - onGraphStart(api: HostAPI): Promise; - onGraphStop(api: HostAPI): Promise; - }; -} - -export interface BoardServerProject extends Entity { - board?: Board; -} - -export interface User { - username: Username; - apiKey: UserApiKey; - secrets: Secrets /* Used in preference to Board Server equivalents */; -} - -export type Secrets = Map; - -export type Permission = { - create: boolean; - retrieve: boolean; - update: boolean; - delete: boolean; -}; - -export interface Board extends Entity { - theme?: string; - descriptor: GraphDescriptor; - runs?: Run[]; - evaluations?: Evaluation[]; -} - -export interface Run { - metadata: { - dateTime: Date; - title?: string; - }; - descriptor: GraphDescriptor; - status: string; -} - -export interface Evaluation { - runs: Run[]; -} diff --git a/packages/breadboard/src/mermaid.ts b/packages/breadboard/src/mermaid.ts deleted file mode 100644 index 4ecfc5ff79a..00000000000 --- a/packages/breadboard/src/mermaid.ts +++ /dev/null @@ -1,207 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * Converts `GraphDescriptor` to Mermaid format - */ - -import type { - Edge, - GraphDescriptor, - NodeDescriptor, - SubGraphs, -} from "./types.js"; - -const template = (edges: string, direction: string) => { - return `%%{init: 'themeVariables': { 'fontFamily': 'Fira Code, monospace' }}%% -graph ${direction}; -${edges} -classDef default stroke:#ffab40,fill:#fff2ccff,color:#000 -classDef input stroke:#3c78d8,fill:#c9daf8ff,color:#000 -classDef output stroke:#38761d,fill:#b6d7a8ff,color:#000 -classDef passthrough stroke:#a64d79,fill:#ead1dcff,color:#000 -classDef slot stroke:#a64d79,fill:#ead1dcff,color:#000 -classDef config stroke:#a64d79,fill:#ead1dcff,color:#000 -classDef secrets stroke:#db4437,fill:#f4cccc,color:#000 -classDef slotted stroke:#a64d79`; -}; - -const unstyledTemplate = (edges: string, direction: string) => { - return `graph ${direction}; -${edges}`; -}; - -const properNodeId = (node: string) => { - // Mermaid gets confused by hyphens in node ids - // For example `get-graph` id will throw a syntax error, because it thinks - // that it sees the `graph` token. - return node && node.replace(/-/g, ""); -}; - -const shape = (descriptor?: NodeDescriptor, idPrefix = "") => { - if (!descriptor) return ""; - const node = descriptor.id; - const prefix = idPrefix ? `${properNodeId(idPrefix)}_` : ""; - const nodeId = `${prefix}${properNodeId(node)}`; - const nodeType = descriptor.type; - const text = `"${nodeType}
    id='${node}'"`; - switch (nodeType) { - case "include": - return `${nodeId}[[${text}]]:::include`; - case "slot": - return `${nodeId}((${text})):::slot`; - case "passthrough": - return `${nodeId}((${text})):::passthrough`; - case "input": - return `${nodeId}[/${text}/]:::input`; - case "secrets": - return `${nodeId}(${text}):::secrets`; - case "output": - return `${nodeId}{{${text}}}:::output`; - default: - return `${nodeId}[${text}]`; - } -}; - -type NodeMap = Map; - -const describeEdge = (edge: Edge, nodeMap: NodeMap, idPrefix = "") => { - const from = edge.from; - const fromNode = shape(nodeMap.get(from), idPrefix); - const to = edge.to; - const toNode = shape(nodeMap.get(to), idPrefix); - const input = edge.in; - const output = edge.out; - const optional = edge.optional; - const constant = edge.constant; - if (output === "*") { - return `${fromNode} -- all --> ${toNode}`; - } - if (output && input) { - if (optional) return `${fromNode} -. "${output}->${input}" .-> ${toNode}`; - if (constant) return `${fromNode} -- "${output}->${input}" --o ${toNode}`; - return `${fromNode} -- "${output}->${input}" --> ${toNode}`; - } - return `${fromNode} --> ${toNode}`; -}; - -class MermaidGenerator { - nodeMap: NodeMap; - edges: Edge[]; - nodes: NodeDescriptor[]; - idPrefix: string; - subgraphs: SubGraphs; - - constructor(graph: GraphDescriptor, idPrefix = "") { - const { edges, nodes } = graph; - this.nodeMap = new Map(nodes.map((node) => [node.id, node])); - this.edges = edges; - this.nodes = nodes; - this.idPrefix = idPrefix; - this.subgraphs = graph.graphs || {}; - } - - handleSlotted(fromNode: NodeDescriptor, idPrefix: string) { - const prefix = idPrefix ? `${properNodeId(idPrefix)}_` : ""; - const type = fromNode.type; - if (type !== "include") return ""; - const slotted = fromNode.configuration?.slotted; - if (!slotted) return ""; - const subgraphs = Object.entries(slotted).map(([name, subgraph]) => - this.describeSubgraph( - subgraph, - name, - "slotted", - fromNode, - `${prefix}${fromNode.id}` - ) - ); - return subgraphs.join("\n"); - } - - handleLambda(fromNode: NodeDescriptor, idPrefix: string) { - const prefix = idPrefix ? `${properNodeId(idPrefix)}_` : ""; - const board = fromNode.configuration?.board; - if (!board) return ""; - type BoardCapability = { kind: "board"; board: GraphDescriptor }; - const capability = board as BoardCapability; - if (capability.kind !== "board") return ""; - const graph = capability.board; - return this.describeSubgraph( - graph, - fromNode.id, - "lamdba", - fromNode, - `${prefix}${fromNode.id}` - ); - } - - describeSubgraphs(edge: Edge, idPrefix = ""): string { - const fromNode = this.nodeMap.get(edge.from); - if (!fromNode) return ""; - const lamdba = this.handleLambda(fromNode, idPrefix); - const slotted = this.handleSlotted(fromNode, idPrefix); - return `${slotted}${lamdba}`; - } - - describeSubgraph( - subgraph: GraphDescriptor, - name: string, - edgeName?: string, - fromNode?: NodeDescriptor, - idPrefix?: string - ): string { - const subgraphGenerator = new MermaidGenerator(subgraph, idPrefix); - const edges = subgraphGenerator.describeGraph(); - const prefix = this.idPrefix ? `${properNodeId(this.idPrefix)}_` : ""; - const subgraphEdge = - edgeName && fromNode - ? `sg_${properNodeId( - name - )}:::slotted -- "${edgeName}->${edgeName}" --o ${prefix}${properNodeId( - fromNode.id - )}\n` - : ""; - return `\nsubgraph sg_${properNodeId( - name - )} [${name}]\n${edges}\nend\n${subgraphEdge}`; - } - - describeGraph(ignoreSubgraphs = false) { - const result = this.edges.map((edge) => { - const mermEdge = describeEdge(edge, this.nodeMap, this.idPrefix); - const mermSubgraphs = ignoreSubgraphs - ? "" - : this.describeSubgraphs(edge, this.idPrefix); - return `${mermEdge}${mermSubgraphs}`; - }); - const subgraphs = ignoreSubgraphs - ? "" - : Object.entries(this.subgraphs).map(([name, subgraph]) => - this.describeSubgraph( - subgraph, - name, - undefined, - undefined, - `${name}${this.idPrefix}` - ) - ); - return [...result, ...subgraphs].join("\n"); - } -} - -export const toMermaid = ( - graph: GraphDescriptor, - direction = "TD", - unstyled = false, - ignoreSubgraphs = false -) => { - const generator = new MermaidGenerator(graph); - const edges = generator.describeGraph(ignoreSubgraphs); - return unstyled - ? unstyledTemplate(edges, direction) - : template(edges, direction); -}; diff --git a/packages/breadboard/src/new/grammar/base.ts b/packages/breadboard/src/new/grammar/base.ts deleted file mode 100644 index e6e5f49191b..00000000000 --- a/packages/breadboard/src/new/grammar/base.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Schema } from "../../types.js"; - -import { InputsMaybeAsValues, NodeProxy } from "./types.js"; -import { - InputValues, - OutputValues, - NodeHandlerFunction, -} from "../runner/types.js"; - -import { addNodeType } from "./kits.js"; - -const reservedWord: NodeHandlerFunction< - InputValues, - OutputValues -> = async () => { - throw new Error("Reserved word handler should never be invoked"); -}; - -// These get added to the default scope -const inputFactory = addNodeType("input", reservedWord); -const outputFactory = addNodeType("output", reservedWord); - -export const base = { - input: (config: { schema?: Schema; $id?: string }) => inputFactory(config), - output: (config: { schema?: Schema; $id?: string }) => outputFactory(config), -} as { - input: (( - config: { - schema: T; - $id?: string; - } & InputsMaybeAsValues - ) => NodeProxy, T>) & - (( - config?: { - schema?: Schema; - $id?: string; - } & InputsMaybeAsValues - ) => NodeProxy); - output: (( - config: { - schema: T; - $id?: string; - } & InputsMaybeAsValues - ) => NodeProxy>) & - (( - config?: { - schema?: Schema; - $id?: string; - } & InputsMaybeAsValues - ) => NodeProxy>); -}; diff --git a/packages/breadboard/src/new/grammar/board.ts b/packages/breadboard/src/new/grammar/board.ts deleted file mode 100644 index 0305e533d10..00000000000 --- a/packages/breadboard/src/new/grammar/board.ts +++ /dev/null @@ -1,379 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphDescriptor, - Schema, - NodeDescriberFunction, - BreadboardCapability, -} from "../../types.js"; -import { - InputValues, - OutputValues, - BoardFactory, - NodeProxyHandlerFunction, - InputsForGraphDeclaration, - GraphDeclarationFunction, - NodeProxy, - NodeFactory, - InputsMaybeAsValues, - Lambda, - ClosureEdge, - GraphCombinedMetadata, -} from "./types.js"; -import { NodeHandler, NodeHandlerFunction } from "../runner/types.js"; - -import { registerNodeType } from "./kits.js"; -import { BuilderNode } from "./node.js"; -import { BuilderScope, getCurrentContextScope } from "./scope.js"; - -/** - * Implementation of the overloaded board function. - */ -export const board: BoardFactory = ( - optionsOrFn: - | ({ - input?: Schema; - output?: Schema; - graph?: GraphDeclarationFunction; - invoke?: NodeProxyHandlerFunction; - describe?: NodeDescriberFunction; - name?: string; - } & GraphCombinedMetadata) - | GraphDeclarationFunction, - maybeFn?: GraphDeclarationFunction -) => { - const options = typeof optionsOrFn === "object" ? optionsOrFn : {}; - options.graph ??= typeof optionsOrFn === "function" ? optionsOrFn : maybeFn; - - return lambdaFactory(options); -}; - -/** - * Explicit implementations of the overloaded variants, also splitting - * graph generation and code boards. - */ -export const code = < - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, ->( - fn: (inputs: I) => O | PromiseLike -): Lambda> => { - return lambdaFactory({ - invoke: fn as unknown as NodeProxyHandlerFunction, - }) as Lambda>; -}; - -/** - * Actual implementation of all the above - */ -function lambdaFactory( - options: { - input?: Schema; - output?: Schema; - graph?: GraphDeclarationFunction; - invoke?: NodeProxyHandlerFunction; - describe?: NodeDescriberFunction; - name?: string; - } & GraphCombinedMetadata -): Lambda { - if (!options.invoke && !options.graph) - throw new Error("Missing invoke or graph definition function"); - - const lexicalScope = getCurrentContextScope(); - const closureEdgesToWire: ClosureEdge[] = []; - - // Extract board metadata from config. Used in serialize(). - const { url, title, description, version } = options ?? {}; - const configMetadata: GraphCombinedMetadata = { - ...(url ? { url } : {}), - ...(title ? { title } : {}), - ...(description ? { description } : {}), - ...(version ? { version } : {}), - }; - - const inputSchema = options.input; - const outputSchema = options.output; - - const handler: NodeHandler = {}; - - if (options.describe) handler.describe = options.describe; - else if (inputSchema && outputSchema) - handler.describe = async () => ({ inputSchema, outputSchema }); - - if (options.invoke) handler.invoke = options.invoke as NodeHandlerFunction; - - if (options.graph) { - const scope = new BuilderScope({ lexicalScope, serialize: true }); - - scope.asScopeFor(() => { - const inputNode = new BuilderNode( - "input", - scope, - inputSchema ? { schema: inputSchema } : {} - ); - const outputNode = new BuilderNode( - "output", - scope, - outputSchema ? { schema: outputSchema } : {} - ); - - const createAndPinNode = ( - type: string, - config: InputsMaybeAsValues - ) => { - const node = new BuilderNode(type, scope, config); - scope.pin(node); - return node.asProxy(); - }; - - // Create base kit that auto-pins to the scope. - const base = { - input: createAndPinNode.bind(null, "input") as NodeFactory, - output: createAndPinNode.bind(null, "output") as NodeFactory, - }; - - const result = options.graph?.( - inputNode.asProxy() as InputsForGraphDeclaration, - base - ); - - // Nothing returned means that the function must have pinned nodes itself - // using the `base` kit supplied above. - if (result === undefined) return; - - if (result instanceof Promise) - throw new Error("Graph generation function can't be async"); - - let actualOutput = outputNode as BuilderNode; - - if (result instanceof BuilderNode) { - // If the handler returned an output node, serialize it directly, - // otherwise connect the returned node's outputs to the output node. - const node = result.unProxy(); - if (node.type === "output") actualOutput = node; - else outputNode.addInputsFromNode(node); - } else if (typeof result === "object") { - // Otherwise wire up all keys of the returned object to the output. - outputNode.addInputsAsValues( - result as InputsMaybeAsValues - ); - } else { - throw new Error( - `Unexpected return ${typeof result} value from graph declaration` - ); - } - - // Pin the resulting graph. Note: This might not contain either of the - // input or output nodes created above, if e.g. a new input node was - // created and an output node was returned. - scope.pin(actualOutput); - })(); - - // Add closure wires from parent scopes, if any - if (scope.getClosureEdges().length > 0) { - // This input node will receive all closure wires into the new graph. - const closureInput = new BuilderNode("input", scope, { - $id: "closure-input", - }); - scope.pin(closureInput); - - for (const edge of scope.getClosureEdges()) { - // Connect closure input to destination node - const { to, out, in: in_ } = edge; - const wire = `$l-${out}-${to.id}`; - to.addIncomingEdge(closureInput, wire, in_, true); - - // Wire upwards. This has to wait until the end of this function because - // we first need the lambda node, and that in turn needs to serialize - // this graph first. - closureEdgesToWire.push({ ...edge, to: closureInput, in: wire }); - } - } - - scope.compactPins(); - const numGraphs = scope.getPinnedNodes().length; - - if (numGraphs !== 1) - if (numGraphs === 0) - throw new Error( - "If not returning a graph, use `base.input` and `base.output`." - ); - else - throw new Error( - `Expected exactly one graph, but got ${numGraphs}. Are ${scope - .getPinnedNodes() - .map((node) => node.id) - .join(", ")} maybe disjoint?` - ); - - handler.graph = scope; - } - - let lambdaNode: - | BuilderNode< - { board: BreadboardCapability }, - { board: BreadboardCapability } - > - | undefined = undefined; - - // TODO: Fix for closures, probably create a graph with an invoke node and - // re-register name with that as handler. But first we need to get cross-scope - // wiring right. - if (options.name) - registerNodeType(options.name, handler as unknown as NodeHandler); - - // When this factory is called, create node with handler and return as proxy. - // But if this is a closure, i.e. there are incoming wires to the lambda node - // (= like a closure, it reads from other nodes in its parent lexical scope), - // then invoke said lambda by reading the board capability it creates. - const factory = ((config?: InputsMaybeAsValues) => { - if ( - !lambdaNode || - (lambdaNode.incoming.length === 0 && closureEdgesToWire.length == 0) - ) - return new BuilderNode( - handler, - getCurrentContextScope(), - config - ).asProxy(); - else - return new BuilderNode("invoke", getCurrentContextScope(), { - ...config, - $board: lambdaNode.asProxy().board, - }); - }) as Lambda; - - // Serializable: - - // (Will be called and then overwritten by `createLambda` below - // once this turns into a closure) - factory.serialize = async (metadata?: GraphCombinedMetadata) => { - const node = new BuilderNode(handler, lexicalScope); - const [singleNode, graph] = await node.serializeNode(); - - // If there is a subgraph that is invoked, just return that. - if (graph) { - if (singleNode.type !== "invoke") - throw new Error("Unexpected node with graph"); - return { ...configMetadata, ...metadata, ...graph } as GraphDescriptor; - } - // Otherwise build a graph around the node: - else - return { - ...configMetadata, - ...metadata, - edges: [ - { from: `${singleNode.id}-input`, to: singleNode.id, out: "*" }, - { from: singleNode.id, to: `${singleNode.id}-output`, out: "*" }, - ], - nodes: [ - { - id: `${singleNode.id}-input`, - type: "input", - configuration: inputSchema ? { schema: inputSchema } : {}, - }, - singleNode, - { - id: `${singleNode.id}-output`, - type: "output", - configuration: outputSchema ? { schema: outputSchema } : {}, - }, - ], - }; - }; - - // ClosureNodeInterface: - - // Creates a lambda node if this lambda is used as a closure, i.e. it accesses - // wires from nodes in it's lexical scope, or it's passed as a value, i.e. a - // BoardCapability needs to be created. Those wires will be wired to this - // node, which then passes the values to the lambda when invoked. For now it - // does that by adding those values to the `args` field in the serialized - // graph. And it outputs a `BoardCapability` that can be invoked. In the - // future we'll replace the latter with first class support of factories. - function getLambdaNode() { - if (lambdaNode) return lambdaNode; - - const serialized = factory.serialize(); - - // HACK: Since node creation is synchronous, we put a promise for the board - // capability here. BuilderNode.serializeNode() awaits that then. - lambdaNode = new BuilderNode("lambda", lexicalScope, { - board: (async () => ({ - kind: "board", - board: { kits: [], ...(await serialized) }, - // kits: because Runner.fromBoardCapability checks for that. - }))() as unknown as BreadboardCapability, - }); - - // Replace the serialize function with one that returns a graph with that - // lambda node and an invoke node, not the original graph. - factory.serialize = async (metadata?: GraphCombinedMetadata) => { - // If there are no incoming wires to the lambda node, it's not a closure - // and we can just return the original board. - if (lambdaNode?.incoming.length === 0 && closureEdgesToWire.length === 0) - return await serialized; - - const invoke = new BuilderNode("invoke", getCurrentContextScope(), { - $board: lambdaNode?.asProxy().board, - }); - - return invoke.serialize({ ...configMetadata, ...metadata }); - }; - - return lambdaNode; - } - - // Return wire from lambdaNode that will generate a BoardCapability - factory.getBoardCapabilityAsValue = () => - lambdaNode !== undefined && - (lambdaNode.incoming.length > 0 || closureEdgesToWire.length > 0) - ? lambdaNode.asProxy().board - : ((async () => ({ - kind: "board", - board: { kits: [], ...(await factory.serialize()) }, - }))() as Promise); - - // Access to factory as if it was a node means accessing the closure node. - // This makes otherNode.to(factory) work. - factory.unProxy = () => getLambdaNode().unProxy() as unknown as BuilderNode; - - // Allow factory.in(...incoming wires...). - // - // Note: factory.to() is not supported as there are no outgoing wires. To - // access to `board` output, wire the factory directly. In the future we'll - // get rid of BoardCapability and treat node factories as first class entities. - // - factory.in = (inputs: Parameters[0]) => { - getLambdaNode().in(inputs); - return factory as unknown as NodeProxy; - }; - - for (const { scope: fromScope, from, out, in: in_ } of closureEdgesToWire) { - // If we reached the source scope, connect source node to lambda - if (fromScope === lexicalScope) - getLambdaNode().addIncomingEdge(from, out, in_, true); - // Otherwise add closure edge to the lambda node's scope - else - lexicalScope.addClosureEdge({ - scope: fromScope, - from, - to: getLambdaNode(), - out, - in: in_, - }); - } - - return factory; -} - -export function isLambda(factory: unknown): factory is Lambda { - return ( - typeof factory === "function" && - typeof (factory as Lambda).getBoardCapabilityAsValue === "function" - ); -} diff --git a/packages/breadboard/src/new/grammar/closure.ts b/packages/breadboard/src/new/grammar/closure.ts deleted file mode 100644 index 6bddc537e64..00000000000 --- a/packages/breadboard/src/new/grammar/closure.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * Closure - * - * When a `board()` turns into a closure because data is wired in, The behavior - * changes: - * - * As soon as the first input is wired to what is returned by `board()`, e.g. - * by calling `myBoard.in({ ...})` or `otherNode.to(myBoard)`, a `closure` - * node is being created (in the lexical scope where `board` was called), and - * those wires go into it. The `closure` node will have a `$board` output, - * formatted as `BoardCapability` that includes the serialized graph of the node - * that the board was originally about and with all the incoming inputs in - * `args` of the serialized graph. - * - * If passed as an input to another node, it appears as if it was a - * Value with a key of `$prompt`, attached to the closure node. - * This happens inside `BuilderNode.addInputsAsValues`, which then turns it into - * a wire. - * - * If invoked itself, it will do the above and then create an `invoke` node that - * reads that `$board` and invokes the closure. - * - * When a closure is received as an input and then invoked (`inputs.closure()` - * or `inputs.closure.invoke()`), it'll be turned into a wire from that input to - * a newly created `invoke` node and invoked. This happens in `Value.invoke` and - * NodeProxy's default handler for proxied methods that aren't reserved words. - * - * If serialized, it'll return the graph hanging off the `invoke` node above. - * - * Note that if you want to return the serialized graph of the closure, then you - * can create a board around the definition and return an output `{ myBoard }` - * and run the the outer board. This will compute the additional input values - * and add them. `await`ing the output of the outer board automatically - * serializes the closure graph if it wasn't already. - */ diff --git a/packages/breadboard/src/new/grammar/kits.ts b/packages/breadboard/src/new/grammar/kits.ts deleted file mode 100644 index 4f2e722c210..00000000000 --- a/packages/breadboard/src/new/grammar/kits.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { InputsMaybeAsValues, NodeFactory } from "./types.js"; -import { InputValues, OutputValues, NodeHandler } from "../runner/types.js"; -import { - Kit, - KitConstructor, - NodeFactory as OriginalNodeFactory, -} from "../../types.js"; - -import { BuilderNode } from "./node.js"; -import { handlersFromKit } from "../runner/kits.js"; -import { getCurrentContextScope } from "./scope.js"; - -export function addNodeType( - name: string | undefined, - handler: NodeHandler -): NodeFactory { - if (name) registerNodeType(name, handler as unknown as NodeHandler); - return ((config?: InputsMaybeAsValues) => { - return new BuilderNode( - name ?? handler, - getCurrentContextScope(), - config - ).asProxy(); - }) as unknown as NodeFactory; -} - -export function registerNodeType(name: string, handler: NodeHandler) { - getCurrentContextScope().addHandlers({ [name]: handler }); -} - -// Extracts handlers from kits and creates node factories for them. -export function addKit( - ctr: KitConstructor, - namespacePrefix = "" -): { [key: string]: NodeFactory } { - const kit = new ctr({} as unknown as OriginalNodeFactory); - const handlers = handlersFromKit(kit); - const removeNamespacePrefix = namespacePrefix - ? (name: string) => { - return name.startsWith(namespacePrefix) - ? name.slice(namespacePrefix.length) - : name; - } - : (name: string) => name; - return Object.fromEntries( - Object.entries(handlers).map(([name, handler]) => [ - removeNamespacePrefix(name), - addNodeType(name, handler), - ]) - ); -} diff --git a/packages/breadboard/src/new/grammar/node.ts b/packages/breadboard/src/new/grammar/node.ts deleted file mode 100644 index dec5835c59e..00000000000 --- a/packages/breadboard/src/new/grammar/node.ts +++ /dev/null @@ -1,589 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - InputsMaybeAsValues, - NodeProxy, - NodeProxyMethods, - AbstractValue, - BuilderNodeInterface, - BuilderNodeConfig, -} from "./types.js"; -import { - InputValues, - OutputValues, - NodeHandler, - NodeTypeIdentifier, - NodeValue, - Serializeable, - KeyMap, - AbstractNode, - OptionalIdConfiguration, - ScopeInterface, -} from "../runner/types.js"; -import { - GraphDescriptor, - NodeDescriptor, - Schema, - InputValues as OriginalInputValues, -} from "../../types.js"; - -import { BaseNode } from "../runner/node.js"; -import { BuilderScope } from "./scope.js"; -import { Value, isValue } from "./value.js"; -import { isLambda } from "./board.js"; - -// eslint-disable-next-line @typescript-eslint/ban-types -const serializeFunction = (name: string, handlerFn: Function) => { - let code = handlerFn.toString(); - - const arrowFunctionRegex = /(?:async\s*)?(\w+|\([^)]*\))\s*=>\s*/; - const traditionalFunctionRegex = - /(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)\s*\{/; - - if (arrowFunctionRegex.test(code)) { - code = `const ${name} = ${code};`; - } else { - const match = traditionalFunctionRegex.exec(code); - if (match === null) throw new Error("Unexpected serialization: " + code); - else name = match[1] || name; - } - return [code, name]; -}; - -export class BuilderNode< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, - > - extends BaseNode - implements - BuilderNodeInterface, - NodeProxyMethods, - PromiseLike, - Serializeable -{ - #promise: Promise; - #resolve?: (value: O | PromiseLike) => void; - #reject?: (reason?: unknown) => void; - - #scope: BuilderScope; - #handler?: NodeHandler; - - constructor( - handler: NodeTypeIdentifier | NodeHandler, - scope: BuilderScope, - config: BuilderNodeConfig = {} - ) { - const $id = - !isBuilderNodeProxy(config) && - !(config instanceof AbstractNode) && - !isLambda(config) && - !isValue(config) && - (config as OptionalIdConfiguration).$id; - - super( - handler, - scope, - $id ? ({ $id } as Partial & OptionalIdConfiguration) : {} - ); - - this.#scope = scope; - - if (typeof handler !== "string") this.#handler = handler; - - if (isBuilderNodeProxy(config)) { - this.addInputsFromNode(config.unProxy()); - } else if (config instanceof AbstractNode) { - this.addInputsFromNode(config); - } else if (isLambda(config)) { - this.addInputsAsValues({ - $board: config.getBoardCapabilityAsValue(), - } as InputsMaybeAsValues); - } else if (isValue(config)) { - this.addInputsFromNode(...config.asNodeInput()); - } else { - if ((config as OptionalIdConfiguration).$id !== undefined) { - delete (config as OptionalIdConfiguration)["$id"]; - } - const metadata = (config as OptionalIdConfiguration).$metadata; - if (metadata !== undefined) { - this.metadata = metadata; - delete (config as OptionalIdConfiguration)["$metadata"]; - } - this.addInputsAsValues(config as InputsMaybeAsValues); - } - - // Set up spread value, so that { ...node } as input works. - (this as unknown as { [key: string]: BaseNode })[this.#spreadKey()] = - this; - - this.#promise = new Promise((resolve, reject) => { - this.#resolve = resolve; - this.#reject = reject; - }); - } - - addInputsAsValues(values: InputsMaybeAsValues) { - // Split into constants and nodes - const constants: Partial = {}; - const nodes: [AbstractNode, KeyMap, boolean, Schema | undefined][] = []; - - Object.entries(values).forEach(([key, value]) => { - // This turns something returned by board() into a BoardCapability, which - // is going to be either a Promise for a BoardCapability (assigned to - // constants below) or an AbstractValue to one. - if (isLambda(value)) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - value = value.getBoardCapabilityAsValue() as any; - } - if (isValue(value)) { - nodes.push(value.as(key).asNodeInput()); - } else if (value instanceof AbstractNode || isBuilderNodeProxy(value)) { - nodes.push([ - isBuilderNodeProxy(value) ? value.unProxy() : value, - { [key]: key }, - false, - undefined, // Defers inference of schema from node to serialization - ]); - } else { - constants[key] = value as NodeValue; - } - }); - - this.configuration = { ...this.configuration, ...constants }; - nodes.forEach((node) => this.unProxy().addInputsFromNode(...node)); - } - - // Add inputs from another node as edges - addInputsFromNode( - from: AbstractNode, - keymap: KeyMap = { "*": "" }, - constant?: boolean, - schema?: Schema - ) { - const keyPairs = Object.entries(keymap); - if (keyPairs.length === 0) { - // Add an empty edge: Just control flow, no data moving. - this.addIncomingEdge(from, "", "", constant); - } else { - keyPairs.forEach(([fromKey, toKey]) => { - // "*-" means "all outputs from " and comes from using a node in - // a spread, e.g. newNode({ ...node, $id: "id" } - if (fromKey.startsWith("*-")) { - fromKey = "*"; - toKey = ""; - } - - this.unProxy().addIncomingEdge( - isBuilderNodeProxy(from) ? from.unProxy() : from, - fromKey, - toKey, - constant, - schema - ); - }); - } - } - - addIncomingEdge( - from: AbstractNode, - out: string, - in_: string, - constant?: boolean, - schema?: Schema - ) { - const fromScope = (from as BuilderNode).#scope; - - // If this is a regular wire, call super method to add it - if (fromScope === this.#scope) { - super.addIncomingEdge(from, out, in_, constant, schema); - return; - } - - // Validate that this is a wire from a parent scope - for ( - let scope = this.#scope as BuilderScope; - scope !== fromScope; - scope = scope.parentLexicalScope as BuilderScope - ) - if (!scope) throw new Error("Only wires from parent scopes allowed"); - - // Don't allow * or empty wires from parent scopes - if (out === "*" || out === "") - throw new Error("Can't use * or empty wires from parent scopes"); - - // Save for board() to add to the graph later - this.#scope.addClosureEdge({ - scope: fromScope, - from: from as BuilderNode, - to: this as BuilderNode, - out, - in: in_, - }); - } - - async invoke(inputs: I, dynamicScope?: ScopeInterface): Promise { - const scope = new BuilderScope({ - dynamicScope, - lexicalScope: this.#scope, - }); - return scope.asScopeFor(async () => { - try { - const handler = this.#handler ?? scope.getHandler(this.type); - - let result: O; - - // Note: The handler might actually return a graph (as a NodeProxy), and - // so the await might triggers its execution. This is what we want. - // - // Awaiting here means that parallel execution isn't possible. - // TODO: Return a promise that knows how to do the rest. Make sure to - // never invoke the handler twice while it is running, though. - // - // TODO: What this should do instead is much closer to what the - // serialization code below does. It should: - // - add an input node, assign the inputs to it - // - call the handler with that input node's proxy (this gives it all - // the values, but as promises) if it supports promises, otherwise - // call it with the values directly. - // - if the handler returns a node (i.e. a graph), and - // - it isn't an output node, add an output node and wire it up - // - execute the graph, and return the output node's outputs - // - otherwise return the handler's return value as result. - const handlerFn = - handler && "invoke" in handler && handler.invoke - ? handler.invoke - : typeof handler === "function" - ? handler - : undefined; - if (handlerFn) { - result = (await handlerFn(inputs, this)) as O; - } else if (handler && typeof handler !== "function" && handler.graph) { - // TODO: This isn't quite right, but good enough for now. Instead what - // this should be in invoking a graph from a lexical scope in a dynamic - // scope. This requires moving state management into the dynamic scope. - const graphs = handler.graph.getPinnedNodes(); - if (graphs.length !== 1) - throw new Error("Expected exactly one graph"); - result = (await scope.invokeOneRound(inputs, graphs[0])) as O; - } else { - throw new Error(`Can't find handler for ${this.id}`); - } - - // Execute graphs returned by the handler as individual results (A full - // graph returned would have already been executed above) - // - // TODO: As a future feature, it would be nice to do this as deep - // traversal, so that developers can return complex structures composed - // of different responses. But only if we support this for regular nodes - // as well. - for (const [key, value] of Object.entries(result)) { - if (value instanceof BuilderNode) - result[key as keyof O] = (await value)[key]; - else if (isValue(value)) - result[key as keyof O] = (await value) as O[keyof O]; - else if (isLambda(value)) - result[key as keyof O] = - (await value.getBoardCapabilityAsValue()) as O[keyof O]; - } - - // Resolve promise, but only on first run - if (this.#resolve) { - this.#resolve(result); - this.#resolve = this.#reject = undefined; - } - - return result; - } catch (e) { - // Reject promise, but only on first run - if (this.#reject) { - this.#reject(e); - this.#resolve = this.#reject = undefined; - } - throw e; - } - })(); - } - - // TODO:BASE Special casing the function case (which is most of the code - // here), everything else is the same, but really just the first few lines - // here. - async serializeNode(): Promise<[NodeDescriptor, GraphDescriptor?]> { - // HACK: See board.getClosureNode() and - // board.getBoardCapabilityAsValue() for why this is needed. There we - // create a node that has a board capability as input, but serializing the - // graph is async, while node creation isn't. So we wait until here to - // await the serialized BoardCapability. To fix: Make node factories a - // first class object, which should inherently move serializing the - // subgraph to here (and never serialize subgraphs if their parent graphs - // aren't serialized either). - for (const [key, value] of Object.entries(this.configuration)) - if (value instanceof Promise) - this.configuration[key as keyof typeof this.configuration] = - await value; - - if (this.type !== "fn") { - return super.serializeNode(); - } - - const scope = new BuilderScope({ - lexicalScope: this.#scope, - serialize: true, - }); - - const handler = this.#handler ?? scope.getHandler(this.type); - - // If this is a graph node, save it as a subgraph (returned as second value) - // and turns this into an invoke node. - if (handler && typeof handler !== "function" && handler.graph) { - const node: NodeDescriptor = { - id: this.id, - type: "invoke", - configuration: { - ...(this.configuration as OriginalInputValues), - path: "#" + this.id, - }, - }; - - const graphs = handler.graph.getPinnedNodes(); - if (graphs.length !== 1) throw new Error("Expected exactly one graph"); - - return [node, await scope.serialize({}, graphs[0])]; - } else { - // Else, serialize the handler itself and return a runJavascript node. - const handlerFn = - handler && "invoke" in handler && handler.invoke - ? handler.invoke - : typeof handler === "function" - ? handler - : undefined; - if (!handlerFn) - throw new Error(`Handler for ${this.type} in ${this.id} not found`); - - const jsFriendlyId = this.id.replace(/-/g, "_"); - const [code, name] = serializeFunction(jsFriendlyId, handlerFn); - - const node = { - id: this.id, - type: "runJavascript", - configuration: { - ...(this.configuration as OriginalInputValues), - code, - name, - raw: true, - }, - metadata: this.metadata, - }; - - return [node]; - } - } - - /** - * Creates a proxy for a Node that is used when constructing a graph. - * - * const node = originalNode.asProxy(); - * - * It acts as a Promise for the Node's output by implementing a `then` method: - * const output = await node; - * - * It acts a proxy for Promises for the Node's output's members. - * const field = await node.field; - * - * You can still call methods on the Node: - * node.to(nextNode); - * - * You can do that on output members too: - * node.field.to(nextNode); - * - * This even works for its methods and `then` and other reserved words: - * const to = await node.to; - * const thenValue = await node.then; // note: not then() - * node.then.to(nextNode); // send the value of `then` to nextNode - * node.to.to(nextNode); // same for the value of `to`. - * - * - * To achieve this, we use a Proxy that creates instances of Value for each - * requested key, as if it was an output of the node. If there is a method on - * node with the same name, we return a proxy for that method instead, that - * forwards all gets to the Value instance. As this includes the `then` method - * defined on the value, `await node.foo` works, even though `node.foo` is a a - * function. That it is a function is important for `node.then`, so that the - * node acts like a Promise as well. - * - */ - // TODO: Hack keys() to make spread work - asProxy(): NodeProxy { - return new Proxy(this, { - get(target, prop, receiver) { - if (typeof prop === "string") { - const value = new Value( - target as unknown as BuilderNode, - target.#scope as BuilderScope, - prop - ); - - let method = target[prop as keyof BuilderNode] as () => void; - // .to(), .in(), etc. call the original method: - if (method && typeof method === "function") - method = method.bind(target); - // Otherwise, default "method" is to invoke the lambda represented by the value - else - method = ((config?: BuilderNodeConfig) => - value.invoke(config)).bind(value); - - return new Proxy(method, { - get(_, key, __) { - const maybeMethod = Reflect.get(value, key, value); - return typeof maybeMethod === "function" - ? maybeMethod.bind(value) - : maybeMethod; - }, - ownKeys(_) { - return Reflect.ownKeys(value).filter( - (key) => typeof key === "string" - ); - }, - }); - } else { - return Reflect.get(target, prop, receiver); - } - }, - ownKeys(target) { - return [target.#spreadKey()]; - }, - }) as unknown as NodeProxy; - } - - /** - * Retrieve underlying node from a NodeProxy. Use like this: - * - * if (thing instanceof BuilderNode) { const node = thing.unProxy(); } - * - * @returns A BuilderNode that is not a proxy, but the original BuilderNode. - */ - unProxy() { - return this; - } - - /**** - * Implementations of NodeProxyInterface, used for constructing Graphs, - * typically invoked on this.asProxy(). - */ - /** - * Makes the node (and its proxy) act as a Promise, which returns the output - * of the node. This trigger the execution of the graph built up so far. - * - * this.#promise is a Promise that gets resolved with the (first and only the - * first) invoke() call of the node. It is resolved with the outputs. - */ - then( - onfulfilled?: ((value: O) => TResult1 | PromiseLike) | null, - onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null - ): PromiseLike { - if (this.#scope.serializing()) - throw new Error( - `Can't \`await\` on ${this.id} in board declaration. ` + - `Did you mean to use \`code\` instead of \`board\`?` - ); - try { - // It's ok to call this multiple times: If it already run it'll only do - // something if new nodes or inputs were added (e.g. between await calls) - this.#scope.invoke(this as unknown as BaseNode).catch((e) => { - if (onrejected) - return Promise.reject(e).catch(this.#scope.asScopeFor(onrejected)); - else throw e; - }); - - return this.#promise.then( - onfulfilled && this.#scope.asScopeFor(onfulfilled), - onrejected && this.#scope.asScopeFor(onrejected) - ); - } catch (e) { - if (onrejected) - return Promise.reject(e).catch(this.#scope.asScopeFor(onrejected)); - else throw e; - } - } - - to< - ToO extends OutputValues = OutputValues, - ToC extends InputValues = InputValues, - >( - to: - | NodeProxy - | NodeTypeIdentifier - | NodeHandler, - config?: ToC - ): NodeProxy { - const toNode = isBuilderNodeProxy(to) - ? to.unProxy() - : new BuilderNode( - to as NodeTypeIdentifier | NodeHandler & ToC, ToO>, - this.#scope, - config as Partial & ToC - ); - - // TODO: Ideally we would look at the schema here and use * only if - // the output is open ended and/or not all fields are present all the time. - toNode.addInputsFromNode(this as unknown as BaseNode, { "*": "" }); - - return (toNode as BuilderNode).asProxy(); - } - - // This doesn't do any type checking on the inputs. - // - // TODO: See whether that's somehow possible. The main problem is that - // node. is typed for the outputs. We could add a new InputValue type - // and generate those from node.in().field so that the final syntax could be - // - `toNode.in({ toField: fromNode.in().fromField) }` or - // - `toNode.in({ field: fromNode.in() })` - // - // That is, today .in() returns itself, and in with this change, it would - // return a proxy object typed with the input types. - in( - inputs: - | NodeProxy> - | InputsMaybeAsValues - | AbstractValue - ) { - if (inputs instanceof BaseNode) { - this.addInputsFromNode(inputs); - } else if (isValue(inputs)) { - this.addInputsFromNode(...inputs.asNodeInput()); - } else { - this.addInputsAsValues(inputs as InputsMaybeAsValues); - } - return this.asProxy(); - } - - as(keymap: KeyMap): Value { - return new Value( - this as unknown as BuilderNode, - this.#scope, - keymap - ); - } - - keys() { - return [this.#spreadKey()]; - } - - #spreadKey() { - return "*-" + this.id; - } -} - -// This will also match Lambdas, since they behave like a subset of -// BuilderNodeProxy. -// -// TODO: Identify where they don't and possibly use a different is* there. -export function isBuilderNodeProxy< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, ->(node: unknown): node is BuilderNodeInterface { - return typeof (node as BuilderNodeInterface).unProxy === "function"; -} diff --git a/packages/breadboard/src/new/grammar/scope.ts b/packages/breadboard/src/new/grammar/scope.ts deleted file mode 100644 index 50e12617a03..00000000000 --- a/packages/breadboard/src/new/grammar/scope.ts +++ /dev/null @@ -1,122 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - BuilderScopeInterface, - BuilderNodeInterface, - ClosureEdge, - GraphCombinedMetadata, -} from "./types.js"; -import { AbstractNode, ScopeConfig } from "../runner/types.js"; - -import { Scope } from "../runner/scope.js"; -import { BuilderNode } from "./node.js"; -import { GraphDescriptor } from "../../types.js"; - -/** - * Adds syntactic sugar to support unproxying and serialization of nodes/graphs. - */ -export class BuilderScope extends Scope implements BuilderScopeInterface { - #isSerializing: boolean; - #closureEdges: ClosureEdge[] = []; - - parentLambdaNode?: BuilderNode; - - // TODO:BASE, config of subclasses can have more fields - constructor( - config: ScopeConfig & { - serialize?: boolean; - parentLambda?: BuilderNode; - } = {} - ) { - super(config); - this.#isSerializing = config.serialize ?? false; - this.parentLambdaNode = config.parentLambda; - } - - async serialize( - metadata?: GraphCombinedMetadata, - node?: AbstractNode - ): Promise { - return super.serialize( - metadata, - node && typeof (node as BuilderNodeInterface).unProxy === "function" - ? (node as BuilderNodeInterface).unProxy() - : node - ); - } - - serializing() { - return this.#isSerializing; - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - asScopeFor any>(fn: T): T { - return ((...args: unknown[]) => { - const oldScope = swapCurrentContextScope(this); - try { - return fn(...args); - } finally { - swapCurrentContextScope(oldScope); - } - }) as T; - } - - addClosureEdge(edge: ClosureEdge) { - this.#closureEdges.push(edge); - } - - getClosureEdges() { - return this.#closureEdges; - } -} - -/** - * The following is inspired by zone.js, but much simpler, and crucially doesn't - * require monkey patching. - * - * Instead, we use a global variable to store the current scope, and swap it - * out when we need to run a function in a different context. - * - * Scope.asScopeFor() wraps a function that runs with that Scope as context. - * - * action and any nodeFactory will run with the current Scope as context. That - * is, they remember the Scope that was active when they were created. - * - * Crucially (and that's all we need from zone.js), {NodeImpl,Value}.then() call - * onsuccessful and onrejected with the Scope as context. So even if the - * context changed in the meantime, due to async calls, the rest of a flow - * defining function will run with the current Scope as context. - * - * This works because NodeImpl and Value are PromiseLike, and so their then() is - * called when they are awaited. Importantly, there is no context switch between - * then() and the onsuccessful or onrejected call, if called from a Promise - * then(), including a Promise.resolve().then (This makes it robust in case the - * containing function isn't immediately awaited and so possibly Promises are - * being scheduled). However, there is a context switch between the await and - * the then() call, and so the context might have changed. That's why we - * remember the scope on the node object. - * - * One requirement from this that there can't be any await in the body of a flow - * or action function, if they are followed by either node creation or flow - * calls. This is also a requirement for restoring state after interrupting a - * flow. - */ - -let currentContextScope: BuilderScope | undefined = undefined; - -export function getCurrentContextScope() { - // Initialize on first use. - if (!currentContextScope) currentContextScope = new BuilderScope(); - - return currentContextScope; -} - -export function swapCurrentContextScope(scope: BuilderScope) { - const oldScope = getCurrentContextScope(); - currentContextScope = scope; - return oldScope; -} diff --git a/packages/breadboard/src/new/grammar/types.ts b/packages/breadboard/src/new/grammar/types.ts deleted file mode 100644 index bc9300bf592..00000000000 --- a/packages/breadboard/src/new/grammar/types.ts +++ /dev/null @@ -1,335 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphMetadata } from "@google-labs/breadboard-schema/graph.js"; -import { - BreadboardCapability, - NodeDescriberFunction, - GraphInlineMetadata, - Schema, - BehaviorSchema, -} from "../../types.js"; - -import { - NodeValue as BaseNodeValue, - OutputValue, - NodeTypeIdentifier, - NodeHandler, - KeyMap, - AbstractNode, - Serializeable, -} from "../runner/types.js"; - -export type GraphCombinedMetadata = GraphInlineMetadata & { - metadata?: GraphMetadata; -}; - -export type NodeValue = - | BaseNodeValue - | NodeFactory; -export type InputValues = { [key: string]: NodeValue }; -export type OutputValues = { [key: string]: NodeValue }; - -export type InputsMaybeAsValues< - T extends InputValues, - NI extends InputValues = InputValues, -> = Partial<{ - [K in keyof T]: AbstractValue | NodeProxy> | T[K]; -}> & { - [key in string]: - | AbstractValue - | NodeProxy> - | NodeValue; -}; - -export type OutputsMaybeAsValues< - T extends OutputValuesOrUnknown, - NI extends InputValues = InputValues, -> = Partial<{ - [K in keyof T]: - | AbstractValue - | NodeProxy> - | T[K] - | unknown; -}> & { - [key in string]: - | AbstractValue - | NodeProxy> - | NodeValue; -}; - -export type OutputValuesOrUnknown = { [key: string]: NodeValue | unknown }; -export type ProjectBackToOutputValues = { - [K in keyof O]: O[K] extends NodeValue ? O[K] : NodeValue; -}; - -export type NodeFactory< - I extends InputValues = InputValues, - O extends OutputValuesOrUnknown = OutputValuesOrUnknown, -> = ( - config?: - | AbstractNode - | AbstractValue - | InputsMaybeAsValues -) => NodeProxy; - -export type InputsForHandler = { - [K in keyof T]: AbstractValue & - PromiseLike & - ((config?: BuilderNodeConfig) => NodeProxy); -} & { - [key in string]: AbstractValue & PromiseLike; -} & PromiseLike; - -export type InputsForGraphDeclaration = { - [K in keyof T]: AbstractValue & - ((config?: BuilderNodeConfig) => NodeProxy); -} & { - [key in string]: AbstractValue; -}; - -export type OutputsForGraphDeclaration< - T extends OutputValuesOrUnknown, - NI extends InputValues = InputValues, -> = - | ({ - [K in keyof T]: AbstractValue | NodeProxy>; - } & { - [key in string]: - | AbstractValue - | NodeProxy>; - }) - | PromiseLike> // = returning a node - | void; // = returning nothing, i.e. expect nodes to be pinned instead - -export type NodeProxyHandlerFunction< - I extends InputValues = InputValues, - O extends OutputValuesOrUnknown = OutputValuesOrUnknown, -> = ( - inputs: InputsForHandler, - node: AbstractNode> -) => - | O - | PromiseLike - | OutputsMaybeAsValues - | PromiseLike>; - -export type GraphDeclarationFunction< - I extends InputValues = InputValues, - O extends OutputValuesOrUnknown = OutputValuesOrUnknown, -> = ( - inputs: InputsForGraphDeclaration, - base: { [key: string]: NodeFactory } -) => OutputsForGraphDeclaration; - -export type Lambda< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, -> = NodeFactory & Serializeable & ClosureNodeInterface; - -export interface BoardFactory { - /** - * Creates a node factory for a node type that invokes a handler function. - * This version infers the types from the function. - * - * The handler function can either return a graph (in which case it would be - * serialized to a graph), or returns the results of a computation, called at - * runtime and serialized as Javascript. - * - * @param fn Handler or graph creation function - */ - ( - fn: GraphDeclarationFunction - ): Lambda>; - - ( - opts: { - input?: Schema; - output?: Schema; - graph?: GraphDeclarationFunction; - invoke?: NodeProxyHandlerFunction; - describe?: NodeDescriberFunction; - name?: string; - } & GraphCombinedMetadata - ): Lambda>; - - ( - opts: { - input?: Schema; - output?: Schema; - graph?: GraphDeclarationFunction; - invoke?: NodeProxyHandlerFunction; - describe?: NodeDescriberFunction; - name?: string; - } & GraphCombinedMetadata, - fn: GraphDeclarationFunction - ): Lambda>; -} - -export type NodeProxyMethods = { - then( - onfulfilled?: ((value: O) => TResult1 | PromiseLike) | null, - onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null - ): PromiseLike; - to< - ToO extends OutputValues = OutputValues, - ToC extends InputValues = InputValues, - >( - to: - | NodeProxy - | NodeTypeIdentifier - | NodeHandler, - config?: ToC - ): NodeProxy; - in( - inputs: - | NodeProxy> - | InputsMaybeAsValues - | AbstractValue - ): NodeProxy; - as(keymap: KeyMap): AbstractValue; -}; - -export interface BuilderNodeInterface< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, -> extends AbstractNode { - addInputsAsValues(values: InputsMaybeAsValues): void; - addInputsFromNode( - from: AbstractNode, - keymap: KeyMap, - constant?: boolean, - schema?: Schema - ): void; - - asProxy(): NodeProxy; - unProxy(): BuilderNodeInterface; -} - -export type BuilderNodeConfig = - | Partial> - | AbstractValue - | BuilderNodeInterface> - | { $id?: string }; - -export type ClosureNodeInterface< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, -> = Pick, "unProxy"> & - Pick, "in"> & - Pick, "invoke"> & { - getBoardCapabilityAsValue(): - | AbstractValue - | Promise; - }; - -export abstract class AbstractValue - implements PromiseLike -{ - abstract then( - onfulfilled?: - | ((value: T | undefined) => TResult1 | PromiseLike) - | null, - onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null - ): PromiseLike; - - abstract asNodeInput(): [ - AbstractNode, - { [key: string]: string }, - boolean, - Schema, - ]; - - abstract to< - ToO extends OutputValues = OutputValues, - ToC extends InputValues = InputValues, - >( - to: - | NodeProxy & ToC, ToO> - | NodeTypeIdentifier - | NodeHandler & ToC, ToO>, - config?: ToC - ): NodeProxy & ToC, ToO>; - - abstract in( - inputs: - | AbstractNode - | AbstractValue - | InputsMaybeAsValues - ): void; - - abstract as(newKey: string | KeyMap): AbstractValue; - - abstract memoize(): AbstractValue; - - abstract invoke(config?: BuilderNodeConfig): NodeProxy; - - abstract isUnknown(): AbstractValue; - abstract isString(): AbstractValue; - abstract isNumber(): AbstractValue; - abstract isBoolean(): AbstractValue; - abstract isArray(): AbstractValue; - abstract isObject(): AbstractValue<{ [key: string]: NodeValue }>; - - abstract title(title: string): AbstractValue; - abstract format(format: string): AbstractValue; - - abstract description(description: string): AbstractValue; - abstract examples(...examples: string[]): AbstractValue; - abstract default(value: string): AbstractValue; - abstract optional(): AbstractValue; - - /** - * Specifies additional behaviors for the value. - * Use this to better identify the shape of the value. - * @see [BehaviorSchema] - * @param tags -- a list of behavior tags to apply to the - * value. Must be one of the values in `BehaviorSchema`. - */ - abstract behavior(...tags: BehaviorSchema[]): AbstractValue; -} - -/** - * Intersection between a Node and a Promise for its output: - * - Has all the output fields as Value instances. - * - Has all the methods of the NodeProxyInterface defined above. - * - Including then() which makes it a PromiseLike - */ -export type NodeProxy< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, -> = { - [K in keyof O]: AbstractValue & ((...args: unknown[]) => unknown); -} & { - [key in string]: AbstractValue & ((...args: unknown[]) => unknown); -} & NodeProxyMethods; - -export interface ClosureEdge { - scope: BuilderScopeInterface; - from: BuilderNodeInterface; - to: BuilderNodeInterface; - out: string; - in: string; -} - -export interface BuilderScopeInterface { - /** - * Swap global scope with this one, run the function, then restore - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - asScopeFor any>(fn: T): T; - - /** - * Helpers to detect handlers that construct graphs but don't invoke them. - */ - serializing(): boolean; - - /** - * used by board() and node.addIncomingEdges() to auto-wire closures - */ - addClosureEdge(edge: ClosureEdge): void; - getClosureEdges(): ClosureEdge[]; -} diff --git a/packages/breadboard/src/new/grammar/value.ts b/packages/breadboard/src/new/grammar/value.ts deleted file mode 100644 index 6c684c61d0d..00000000000 --- a/packages/breadboard/src/new/grammar/value.ts +++ /dev/null @@ -1,300 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - NodeValue, - InputValues, - InputsMaybeAsValues, - OutputValues, - NodeProxy, - BuilderNodeInterface, - BuilderNodeConfig, - AbstractValue, -} from "./types.js"; -import { - OutputValue, - NodeHandler, - NodeTypeIdentifier, - KeyMap, -} from "../runner/types.js"; -import { BehaviorSchema, Schema } from "../../types.js"; - -import { BuilderNode, isBuilderNodeProxy } from "./node.js"; -import { BuilderScope } from "./scope.js"; - -// Because Value is sometimes behind a function Proxy (see NodeImpl's methods), -// we need to use this approach to identify Value instead instanceof. -export const IsValueSymbol = Symbol("IsValue"); - -export function isValue( - obj: unknown -): obj is Value { - return ( - (typeof obj === "object" || typeof obj === "function") && - (obj as unknown as { [key: symbol]: boolean })[IsValueSymbol] !== undefined - ); -} - -const isSchema = (o: Schema | Schema[]): o is Schema => { - return !Array.isArray(o); -}; - -const getItemSchema = (schema: Schema) => { - if (schema.type === "array") { - schema.items ??= {}; - const itemSchema = isSchema(schema.items) ? schema.items : schema.items[0]; - itemSchema.type ??= "object"; - return itemSchema; - } - return schema; -}; - -export class Value - extends AbstractValue - implements PromiseLike -{ - #node: BuilderNode>; - #scope: BuilderScope; - #keymap: KeyMap; - #constant: boolean; - #schema: Schema; - - constructor( - node: BuilderNode>, - scope: BuilderScope, - keymap: string | KeyMap, - constant = false, - schema = {} - ) { - super(); - this.#node = node; - this.#scope = scope; - this.#keymap = typeof keymap === "string" ? { [keymap]: keymap } : keymap; - (this as unknown as { [key: symbol]: Value })[IsValueSymbol] = this; - this.#constant = constant; - this.#schema = schema; - } - - then( - onfulfilled?: - | ((value: T | undefined) => TResult1 | PromiseLike) - | null, - onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null - ): PromiseLike { - if (Object.keys(this.#keymap).length !== 1) - throw Error("Can't `await` for multiple values"); - return this.#node.then( - (o) => - o && - onfulfilled && - this.#scope.asScopeFor(onfulfilled)(o[Object.keys(this.#keymap)[0]]), - onrejected && this.#scope.asScopeFor(onrejected) - ) as PromiseLike; - } - - asNodeInput(): [ - BuilderNodeInterface>, - { [key: string]: string }, - boolean, - Schema, - ] { - return [this.#node.unProxy(), this.#keymap, this.#constant, this.#schema]; - } - - to< - ToO extends OutputValues = OutputValues, - ToC extends InputValues = InputValues, - >( - to: - | NodeProxy & ToC, ToO> - | NodeTypeIdentifier - | NodeHandler & ToC, ToO>, - config?: ToC - ): NodeProxy & ToC, ToO> { - const toNode = isBuilderNodeProxy(to) - ? to.unProxy() - : new BuilderNode( - to as NodeTypeIdentifier | NodeHandler & ToC, ToO>, - this.#scope, - config as OutputValue & ToC - ); - - toNode.addInputsFromNode( - this.#node as unknown as BuilderNodeInterface, - this.#keymap, - this.#constant, - this.#schema - ); - - return ( - toNode as BuilderNodeInterface & ToC, ToO> - ).asProxy(); - } - - // This doesn't do any type checking on the inputs. - // - // TODO: See whether that's somehow possible. The main problem is that - // node. is typed for the outputs. We could add a new InputValue type - // and generate those from node.in().field so that the final syntax could be - // `toNode.toField.in(fromNode.in().fromField)`. - // - // That is, today .in() on a value returns void and in the future it would - // return that new InputValue type, typed with the right input value from the - // original node. To accomplish this, we'll have to keep passing the - // node input values type through the chain of values and .as() statements. - in( - inputs: - | BuilderNodeInterface - | AbstractValue - | InputsMaybeAsValues - ) { - let invertedMap = Object.fromEntries( - Object.entries(this.#keymap).map(([fromKey, toKey]) => [toKey, fromKey]) - ); - - if (isValue(inputs)) { - invertedMap = inputs.#remapKeys(invertedMap); - this.#node.addInputsFromNode( - inputs.#node, - invertedMap, - inputs.#constant, - inputs.#schema - ); - } else if (isBuilderNodeProxy(inputs)) { - this.#node.addInputsFromNode(inputs.unProxy(), invertedMap); - } else { - this.#node.addInputsAsValues(inputs as InputsMaybeAsValues); - } - } - - as(newKey: string | KeyMap): Value { - let newMap: KeyMap; - if (typeof newKey === "string") { - if (Object.keys(this.#keymap).length !== 1) - throw new Error("Can't rename multiple values with a single string"); - newMap = { [Object.keys(this.#keymap)[0]]: newKey }; - } else { - newMap = this.#remapKeys(newKey); - } - - return new Value( - this.#node, - this.#scope, - newMap, - this.#constant, - this.#schema - ); - } - - memoize() { - return new Value(this.#node, this.#scope, this.#keymap, true, this.#schema); - } - - // Create a node for the lambda that is being sent as this value. At this - // point we can't verify that this actually is a BoardCapability, so we just - // do it and let the runtime throw an error if this wasn't one. - invoke(config?: BuilderNodeConfig): NodeProxy { - return new BuilderNode("invoke", this.#scope, { - ...config, - $board: this, - }).asProxy(); - } - - /** - * The following are type-casting methods that are useful when a node type - * returns generic types but we want to narrow the types to what we know they - * are, e.g. a parser node returning the result as raw wires. - * - * This is also a way to define the schema of a board, e.g. by casting input - * wires and what is returned. - * - * Use as `foo.asString()` or `foo.asNumber()`. `isArray` and `isObject` cast - * to generic arrays and objects. - */ - - isUnknown(): AbstractValue { - delete this.#schema.type; - return this as unknown as AbstractValue; - } - - isString(): AbstractValue { - this.#schema.type = "string"; - return this as unknown as AbstractValue; - } - - isNumber(): AbstractValue { - this.#schema.type = "number"; - return this as unknown as AbstractValue; - } - - isBoolean(): AbstractValue { - this.#schema.type = "boolean"; - return this as unknown as AbstractValue; - } - - isArray(): AbstractValue { - this.#schema.type = "array"; - return this as unknown as AbstractValue; - } - - isObject(): AbstractValue<{ [key: string]: NodeValue }> { - this.#schema.type = "object"; - return this as unknown as AbstractValue<{ - [key: string]: NodeValue; - }>; - } - - title(title: string): AbstractValue { - this.#schema.title = title; - return this; - } - - description(description: string): AbstractValue { - this.#schema.description = description; - return this; - } - - format(format: string): AbstractValue { - const schema = getItemSchema(this.#schema); - schema.format = format; - return this; - } - - examples(...examples: string[]): AbstractValue { - this.#schema.examples = examples; - return this; - } - - default(value: string): AbstractValue { - this.#schema.default = value; - return this; - } - - optional(): AbstractValue { - (this.#schema as Record).$optional = true; - return this; - } - - behavior(...tags: BehaviorSchema[]): AbstractValue { - const schema = getItemSchema(this.#schema); - schema.behavior ??= []; - schema.behavior.push(...tags); - return this; - } - - #remapKeys(newKeys: KeyMap) { - const newMap = { ...this.#keymap }; - Object.entries(newKeys).forEach(([fromKey, toKey]) => { - if (this.#keymap[toKey]) { - newMap[fromKey] = this.#keymap[toKey]; - delete this.#keymap[toKey]; - } else { - newMap[fromKey] = toKey; - } - }); - return newMap; - } -} diff --git a/packages/breadboard/src/new/runner/kits.ts b/packages/breadboard/src/new/runner/kits.ts deleted file mode 100644 index 55a7ea31d44..00000000000 --- a/packages/breadboard/src/new/runner/kits.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { OutputValues, NodeHandlers } from "./types.js"; -import { - Kit, - NodeHandlerFunction, - InputValues as OriginalInputValues, -} from "../../types.js"; - -// TODO: This is wraps classic handlers that expected resolved inputs into -// something that accepts promises. We should either change all handlers to -// support promises or add a flag or something to support either mode. (Almost -// all handlers will immediately await, so it's a bit of a pain...) -export function handlersFromKit(kit: Kit): NodeHandlers { - return Object.fromEntries( - Object.entries(kit.handlers).map(([name, handler]) => { - const handlerFunction = - "invoke" in handler && handler.invoke - ? handler.invoke - : (handler as NodeHandlerFunction); - const describeFunction = - "describe" in handler && handler.describe - ? handler.describe - : undefined; - const describe = describeFunction ? { describe: describeFunction } : {}; - - return [ - name, - { - invoke: async (inputs) => { - return handlerFunction( - (await inputs) as OriginalInputValues, - {} - ) as Promise; - }, - ...describe, - }, - ]; - }) - ); -} diff --git a/packages/breadboard/src/new/runner/node.ts b/packages/breadboard/src/new/runner/node.ts deleted file mode 100644 index 909b80dfa31..00000000000 --- a/packages/breadboard/src/new/runner/node.ts +++ /dev/null @@ -1,175 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphDescriptor, - NodeDescriptor, - InputValues as OriginalInputValues, - Schema, - NodeDescriberResult, -} from "../../types.js"; -import { - InputValues, - OutputValues, - NodeHandler, - NodeTypeIdentifier, - Serializeable, - AbstractNode, - EdgeInterface, - OptionalIdConfiguration, - ScopeInterface, - GraphCombinedMetadata, -} from "./types.js"; - -import { Scope } from "./scope.js"; - -import { IdVendor } from "../../id.js"; -import { NodeMetadata } from "@google-labs/breadboard-schema/graph.js"; - -const nodeIdVendor = new IdVendor(); - -// TODO:BASE Extract base class that isn't opinionated about the syntax. Marking -// methods that should be base as "TODO:BASE" below, including complications. -export class BaseNode< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, - > - extends AbstractNode - implements Serializeable -{ - id: string; - type: string; - outgoing: EdgeInterface[] = []; - incoming: EdgeInterface[] = []; - configuration: Partial = {}; - metadata?: NodeMetadata; - - #handler?: NodeHandler; - - #scope: ScopeInterface; - - constructor( - handler: NodeTypeIdentifier | NodeHandler, - scope: ScopeInterface, - config: Partial & OptionalIdConfiguration = {} - ) { - super(); - - this.#scope = scope; - - if (typeof handler === "string") { - this.type = handler; - } else { - this.type = "fn"; - this.#handler = handler as unknown as NodeHandler< - InputValues, - OutputValues - >; - } - - const { $id, $metadata, ...rest } = config; - - this.id = $id ?? nodeIdVendor.vendId(scope, this.type); - if ($metadata) this.metadata = $metadata; - - this.configuration = rest as Partial; - } - - addIncomingEdge( - from: AbstractNode, - out: string, - in_: string, - constant?: boolean, - schema?: Schema - ) { - if ((from as BaseNode).#scope !== this.#scope) - throw new Error("Can't connect nodes from different scopes"); - - const edge: EdgeInterface = { - to: this as unknown as AbstractNode, - from: from, - out, - in: in_, - schema, - }; - if (constant) edge.constant = true; - - this.incoming.push(edge); - from.outgoing.push(edge); - } - - #getHandlerDescribe(scope: ScopeInterface) { - const handler = this.#handler ?? scope.getHandler(this.type); - return handler && "describe" in handler && handler.describe - ? handler.describe - : undefined; - } - - // In the end, we need to capture the outputs and resolve the promise. But - // before that there is a bit of refactoring to do to allow returning of - // graphs, parallel execution, etc. - // - // The logic from BuilderNode.invoke should be somehow called from here, for - // deserialized nodes that require the Builder environment. - async invoke(inputs: I, dynamicScope?: Scope): Promise { - const scope = dynamicScope ?? (this.#scope as Scope); - - const handler: NodeHandler | undefined = - this.#handler ?? scope.getHandler(this.type); - - let result; - - const handlerFn = - handler && "invoke" in handler && handler.invoke - ? handler.invoke - : typeof handler === "function" - ? handler - : undefined; - - if (handlerFn) { - result = (await handlerFn(inputs, this)) as O; - } else if (handler && typeof handler !== "function" && handler.graph) { - // TODO: This isn't quite right, but good enough for now. Instead what - // this should be in invoking a graph from a lexical scope in a dynamic - // scope. This requires moving state management into the dyanmic scope. - const graphs = handler.graph.getPinnedNodes(); - if (graphs.length !== 1) throw new Error("Expected exactly one graph"); - result = (await scope.invokeOneRound(inputs, graphs[0])) as O; - } else { - throw new Error(`Can't find handler for ${this.id}`); - } - - return result; - } - - async describe( - scope: ScopeInterface = this.#scope, - inputs?: InputValues, - inputSchema?: Schema, - outputSchema?: Schema - ): Promise { - const describe = this.#getHandlerDescribe(scope); - return describe - ? await describe(inputs as OriginalInputValues, inputSchema, outputSchema) - : undefined; - } - - async serialize(metadata?: GraphCombinedMetadata): Promise { - return this.#scope.serialize(metadata, this as unknown as BaseNode); - } - - async serializeNode(): Promise<[NodeDescriptor, GraphDescriptor?]> { - const node: NodeDescriptor = { - id: this.id, - type: this.type, - configuration: this.configuration as OriginalInputValues, - }; - - if (this.metadata) node.metadata = this.metadata; - - return [node]; - } -} diff --git a/packages/breadboard/src/new/runner/scope.ts b/packages/breadboard/src/new/runner/scope.ts deleted file mode 100644 index d3abccaafc8..00000000000 --- a/packages/breadboard/src/new/runner/scope.ts +++ /dev/null @@ -1,417 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - AbstractNode, - GraphCombinedMetadata, - InputValues, - InvokeCallbacks, - NodeHandler, - NodeHandlers, - OutputValues, - ScopeConfig, - ScopeInterface, - StateInterface, -} from "./types.js"; - -import { - GraphDescriptor, - NodeDescriberResult, - Schema, - SubGraphs, -} from "../../types.js"; -import { State } from "./state.js"; - -const buildRequiredPropertyList = (properties: Record) => { - return Object.entries(properties) - .map(([key, value]) => { - const mayHaveOptional = value as Record; - if (mayHaveOptional.$optional) { - delete mayHaveOptional.$optional; - return undefined; - } - return key; - }) - .filter(Boolean) as string[]; -}; - -export class Scope implements ScopeInterface { - parentLexicalScope?: Scope; - parentDynamicScope?: Scope; - - #handlers: NodeHandlers = {}; - #pinnedNodes: AbstractNode[] = []; - - #callbacks: InvokeCallbacks[] = []; - - constructor(config: ScopeConfig = {}) { - this.parentLexicalScope = config.lexicalScope as Scope; - this.parentDynamicScope = config.dynamicScope as Scope; - } - - addHandlers(handlers: NodeHandlers) { - Object.entries(handlers).forEach( - ([name, handler]) => (this.#handlers[name] = handler) - ); - } - - getHandler< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, - >(name: string): NodeHandler | undefined { - return (this.#handlers[name] || - this.parentDynamicScope?.getHandler(name) || - this.parentLexicalScope?.getHandler(name)) as unknown as NodeHandler< - I, - O - >; - } - - pin< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, - >(node: AbstractNode) { - this.#pinnedNodes.push(node); - } - - compactPins() { - const visited = new Set(); - const disjointPins = []; - - for (const node of this.#pinnedNodes) { - if (visited.has(node)) continue; - disjointPins.push(node); - const connected = this.#findAllConnectedNodes(node); - connected.forEach((node) => visited.add(node)); - } - - this.#pinnedNodes = disjointPins; - } - - getPinnedNodes(): AbstractNode[] { - return this.#pinnedNodes; - } - - addCallbacks(callbacks: InvokeCallbacks) { - this.#callbacks.push(callbacks); - } - - #getAllCallbacks(): InvokeCallbacks[] { - // Callbacks are called in reverse order that they are added. Important for - // the `before` callback, which can override execution with output values. - // So while all are called, the last one added that returns something other - // than undefined gets precedence. - return [ - ...this.#callbacks, - ...(this.parentDynamicScope - ? this.parentDynamicScope.#getAllCallbacks() - : []), - ]; - } - - async invoke( - node?: AbstractNode | AbstractNode[] | false, - state: StateInterface = new State() - ): Promise { - try { - if (node !== false) - (node ? (node instanceof Array ? node : [node]) : this.#pinnedNodes) - .flatMap((node) => - this.#findAllConnectedNodes(node).filter( - (node) => state?.missingInputs(node) === false - ) - ) - .forEach((node) => state?.queueUp(node)); - - const callbacks = this.#getAllCallbacks(); - - while (!state.done()) { - for (const callback of callbacks) - if (await callback.stop?.(this, state)) return; - - const node = state.next(); - - const inputs = state.shiftInputs(node); - - let callbackResult: OutputValues | undefined = undefined; - for (const callback of callbacks) - callbackResult ??= await callback.before?.(this, node, inputs); - - // Invoke node, unless before callback already provided a result. - const result = - callbackResult ?? - (await node.invoke(inputs, this).catch((e) => { - return { - $error: { - type: "error", - error: e, - }, - }; - })); - - // Distribute data to outgoing edges, queue up nodes that are ready to - const distribution = state.processResult(node, result); - - // Call after callback - for (const callback of callbacks) { - await callback.after?.(this, node, inputs, result, distribution); - } - - // Abort graph on uncaught errors. - if (distribution.unused.includes("$error")) { - throw (result["$error"] as { error: Error }).error; - } - } - } finally { - // Call done callback - // Note: Only callbacks added to this scope specifically are called - for (const callback of this.#callbacks) { - await callback.done?.(); - } - } - } - - invokeOneRound( - inputs: InputValues = {}, - node: AbstractNode | false | undefined = undefined, - state?: StateInterface - ): Promise { - if ("$state" in inputs) { - state = inputs["$state"] as StateInterface; - delete inputs["$state"]; - } - - let resolver: undefined | ((outputs: OutputValues) => void) = undefined; - const promise = new Promise((resolve) => { - resolver = resolve; - }); - - const scope = new Scope({ dynamicScope: this }); - - scope.addHandlers({ - input: async () => { - return inputs; - }, - output: async (inputs: InputValues | PromiseLike) => { - resolver?.(await inputs); - resolver = undefined; - return inputs; - }, - }); - - let lastNode: AbstractNode | undefined = undefined; - const lastMissingInputs = new Map(); - - let stopState: StateInterface | undefined = undefined; - - scope.addCallbacks({ - stop: (_scope, state) => { - // Once output node was executed, stop execution. - if (!resolver) stopState = state; - return !resolver; - }, - after: (_scope, node, _inputs, _outputs, distribution) => { - // Remember debug information to make the error below more useful. - - lastNode = node; - for (const { node, missing } of distribution.nodes) { - if (missing) { - lastMissingInputs.set(node.id, missing.join(", ")); - } else { - lastMissingInputs.delete(node.id); - } - } - }, - done: () => { - // Make sure we don't wait forever if execution terminates without - // reaching an output node. - resolver?.({ - $error: { - type: "error", - error: new Error( - `Output node never reached. Last node was ${ - lastNode?.id - }.\n\nThese nodes had inputs missing:\n${Array.from( - lastMissingInputs, - ([id, missing]) => ` ${id}: ${missing}` - ).join("\n")}` - ), - }, - }); - }, - }); - - const runner = scope.invoke( - node !== undefined ? node : this.#pinnedNodes, - state - ); - - // Wait for both, return output values, and last state if stopped. - return Promise.all([promise, runner]).then(([outputs]) => ({ - ...outputs, - ...(stopState ? { $state: stopState } : {}), - })); - } - - async serialize( - metadata?: GraphCombinedMetadata, - node?: AbstractNode - ): Promise { - const queue: AbstractNode[] = (node ? [node] : this.#pinnedNodes).flatMap( - (node) => this.#findAllConnectedNodes(node) - ); - - const graphs: SubGraphs = {}; - - const nodes = await Promise.all( - queue.map(async (node) => { - const [nodeDescriptor, subGraph] = await node.serializeNode(); - - // Save subgraphs returned, typically for `invoke` nodes that call - // serialized graphs or functions. - if (subGraph) graphs[nodeDescriptor.id] = subGraph; - - // If `input` or `output` nodes don't have a schema, derive it from - // their wires, calling the respective nodes' describe method. - if ( - (nodeDescriptor.type === "input" || - nodeDescriptor.type === "output") && - !nodeDescriptor.configuration?.schema - ) { - const schema = await this.#addMissingSchemas(node); - if (Object.entries(schema.properties ?? {}).length > 0) - nodeDescriptor.configuration = { - ...nodeDescriptor.configuration, - schema, - }; - } - - return nodeDescriptor; - }) - ); - - const edges = queue.flatMap((node) => - node.outgoing.map((edge) => ({ - from: edge.from.id, - to: edge.to.id, - out: edge.out, - in: edge.in, - ...(edge.constant ? { constant: true } : {}), - })) - ); - - return { ...metadata, edges, nodes, graphs }; - } - - #findAllConnectedNodes(node: AbstractNode) { - const nodes = new Set(); - const queue = [node]; - - while (queue.length) { - const node = queue.shift() as AbstractNode; - if (nodes.has(node)) continue; - nodes.add(node); - node.incoming.forEach((edge) => queue.push(edge.from)); - node.outgoing.forEach((edge) => queue.push(edge.to)); - } - - return [...nodes]; - } - - async #getSchemasForNode( - node: AbstractNode - ): Promise { - const incomingPorts = Object.fromEntries( - node.incoming - .filter((edge) => edge.out !== "" && edge.out !== "*") - .map((edge) => [edge.out, edge.schema ?? {}]) - ); - const outgoingPorts = Object.fromEntries( - node.outgoing - .filter((edge) => edge.out !== "" && edge.out !== "*") - .map((edge) => [edge.out, edge.schema ?? {}]) - ); - - return await node.describe( - this, - node.configuration, - { properties: incomingPorts }, - { properties: outgoingPorts } - ); - } - - async #addMissingSchemas(node: AbstractNode): Promise { - const properties: Schema["properties"] = {}; - const ports = new Set(); - - let required: string[] | undefined = undefined; - - if (node.type === "input") { - const nodes = new Set(); - - // Find all nodes downstream of this input node, note all ports - for (const edge of node.outgoing) - if (edge.out !== "*" && edge.out !== "") { - nodes.add(edge.to); - ports.add(edge.out); - if (edge.schema) properties[edge.out] = edge.schema; - } - - // For each node, get the schema and copy over the ports we care about - for (const toNode of nodes) { - const schema = await this.#getSchemasForNode(toNode); - const schemaPorts = schema?.inputSchema?.properties; - if (schemaPorts) - for (const edge of toNode.incoming) - if (edge.from === node && schemaPorts[edge.in]) - properties[edge.out] = { - ...schemaPorts[edge.in], - ...properties[edge.out], - }; - } - - required = buildRequiredPropertyList(properties); - } else if (node.type === "output") { - const nodes = new Set(); - - // Find all nodes upstream of this output node, note all ports - for (const edge of node.incoming) - if (edge.out !== "*" && edge.out !== "") { - nodes.add(edge.from); - ports.add(edge.in); - if (edge.schema) properties[edge.in] = edge.schema; - } - - // For each node, get the schema and copy over the ports we care about - for (const fromNode of nodes) { - const schema = await this.#getSchemasForNode(fromNode); - const schemaPorts = schema?.outputSchema?.properties; - if (schemaPorts) - for (const edge of fromNode.outgoing) - if (edge.to === node && schemaPorts[edge.out]) - properties[edge.in] = { - ...schemaPorts[edge.out], - ...properties[edge.in], - }; - } - } else { - throw new Error("Can't yet derive schema for non-input/output nodes"); - } - - for (const port of ports) { - if (!properties[port]) { - properties[port] = { type: "string", title: port }; - } else { - properties[port].type ||= "string"; - properties[port].title ||= port; - } - } - - const schema: Schema = { type: "object", properties }; - if (required) schema.required = required; - return schema; - } -} diff --git a/packages/breadboard/src/new/runner/state.ts b/packages/breadboard/src/new/runner/state.ts deleted file mode 100644 index 6d03803560e..00000000000 --- a/packages/breadboard/src/new/runner/state.ts +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - AbstractNode, - InputValues, - OutputValues, - OutputDistribution, - EdgeInterface, - StateInterface, - NodeValue, -} from "./types.js"; - -// TODO: To support parallelism, we need to track which nodes are still pending - -export class State implements StateInterface { - queue: AbstractNode[] = []; - inputs: Map> = new Map(); - constants: Map> = new Map(); - controlWires: Map = new Map(); - haveRun: Set = new Set(); - - queueUp(node: AbstractNode) { - if (!this.queue.includes(node)) this.queue.push(node); - } - - next(): AbstractNode { - if (!this.queue.length) throw new Error("No nodes in queue"); - return this.queue.shift() as AbstractNode; - } - - done() { - return this.queue.length === 0; - } - - /** - * Compute required inputs from edges and compare with present inputs - * - * Required inputs are - * - for all named incoming edges, the presence of any data, irrespective of - * which node they come from - * - at least one of the incoming empty or * wires, if present (TODO: Is that - * correct?) - * - data from at least one node if it already ran - * - * @returns false if none are missing, otherwise string[] of missing inputs. - * NOTE: A node with no incoming wires returns an empty array after first - * run. - */ - missingInputs(node: AbstractNode): string[] | false { - if (node.incoming.length === 0 && this.haveRun.has(node)) return []; - - const requiredKeys = new Set(node.incoming.map((edge) => edge.in)); - - const presentKeys = new Set([ - ...Object.keys(node.configuration), - ...Object.keys(this.constants.get(node) ?? {}), - ]); - for (const [port, values] of (this.inputs.get(node) ?? new Map()).entries()) - if (values.length) presentKeys.add(port); - if (this.controlWires.get(node)?.length) presentKeys.add(""); - - const missingInputs = [...requiredKeys].filter( - (key) => !presentKeys.has(key) - ); - return missingInputs.length ? missingInputs : false; - } - - shiftInputs(node: AbstractNode): I { - const inputs = { ...node.configuration, ...this.constants.get(node) } as I; - - // Shift inputs from queues - const queues = this.inputs.get(node) ?? new Map(); - for (const [port, values] of queues.entries()) - if (values.length > 0) inputs[port as keyof I] = values.shift(); - - // Mark as run, reset control wires - this.haveRun.add(node); - this.controlWires.delete(node); - - return inputs; - } - - processResult(node: AbstractNode, result: OutputValues): OutputDistribution { - const distribution: OutputDistribution = { nodes: [], unused: [] }; - - const unusedPorts = new Set(Object.keys(result)); - for (const edge of node.outgoing) { - const ports = this.distributeResults(edge, result); - ports.forEach((key) => unusedPorts.delete(key)); - - // If it's ready to run, add it to the queue - const missing = this.missingInputs(edge.to); - if (!missing) this.queueUp(edge.to); - - distribution.nodes.push({ node: edge.to, received: ports, missing }); - } - - distribution.unused = [...unusedPorts]; - - return distribution; - } - - distributeResults(edge: EdgeInterface, inputs: InputValues) { - const data = - edge.out === "*" - ? inputs - : edge.out === "" - ? {} - : inputs[edge.out] !== undefined - ? { [edge.in]: inputs[edge.out] } - : {}; - - // Update constants; pverwrite current values if present - if (edge.constant) - this.constants.set(edge.to, { ...this.constants.get(edge.to), ...data }); - - // Regular inputs: Add to the input queues - if (!this.inputs.has(edge.to)) this.inputs.set(edge.to, new Map()); - const queues = this.inputs.get(edge.to); - for (const port of Object.keys(data)) { - if (!queues?.has(port)) queues?.set(port, []); - queues?.get(port)?.push(data[port]); - } - - if (edge.in === "") - this.controlWires.set(edge.to, [ - ...(this.controlWires.get(edge.to) ?? []), - edge.from, - ]); - - // return which wires were used - return Object.keys(data); - } -} diff --git a/packages/breadboard/src/new/runner/types.ts b/packages/breadboard/src/new/runner/types.ts deleted file mode 100644 index 448bee468e0..00000000000 --- a/packages/breadboard/src/new/runner/types.ts +++ /dev/null @@ -1,294 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphMetadata, - NodeMetadata, -} from "@google-labs/breadboard-schema/graph.js"; -import { - NodeDescriptor, - GraphDescriptor, - GraphInlineMetadata, - NodeDescriberFunction, - NodeDescriberResult, - NodeValue as OriginalNodeValue, - Schema, -} from "../../types.js"; - -// TODO:BASE: Same as before, but I added NodeFactory as base type, which is a -// way to encapsulate boards, including lambdas (instead of BoardCapability). -// Can keep it a capability, but this feels quite fundamental. - -export type NodeValue = OriginalNodeValue | PromiseLike | unknown; -export type NodeTypeIdentifier = string; - -export type GraphCombinedMetadata = GraphInlineMetadata & { - metadata?: GraphMetadata; -}; -export type InputValues = { [key: string]: NodeValue }; - -export type OutputValues = { [key: string]: NodeValue }; -export type OutputValue = Partial<{ [key: string]: T }>; - -export type NodeHandlerFunction< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, -> = (inputs: I, node: AbstractNode) => O | PromiseLike; - -export type NodeHandler< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, -> = - | { - invoke?: NodeHandlerFunction; - describe?: NodeDescriberFunction; - graph?: ScopeInterface; // Pinned graph is the node - } - | NodeHandlerFunction; - -export type NodeHandlers = Record< - NodeTypeIdentifier, - NodeHandler ->; - -export interface Serializeable { - serialize( - metadata?: GraphCombinedMetadata - ): Promise | GraphDescriptor; -} - -export type KeyMap = { [key: string]: string }; - -// TODO: Add optional. -export interface EdgeInterface< - FromI extends InputValues = InputValues, - FromO extends OutputValues = OutputValues, - ToI extends InputValues = InputValues, - ToO extends OutputValues = OutputValues, -> { - from: AbstractNode; - to: AbstractNode; - out: string; - in: string; - constant?: boolean; - schema?: Schema; -} - -export type OptionalIdConfiguration = { - $id?: string; - $metadata?: NodeMetadata; -}; - -export abstract class AbstractNode< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, -> implements Serializeable -{ - abstract id: string; - abstract type: string; - abstract outgoing: EdgeInterface[]; - abstract incoming: EdgeInterface[]; - abstract configuration: Partial; - - abstract addIncomingEdge( - from: AbstractNode, - out: string, - in_: string, - constant?: boolean, - schema?: Schema - ): void; - - abstract invoke(inputs: I, dynamicScope?: ScopeInterface): Promise; - abstract describe( - scope?: ScopeInterface, - inputs?: InputValues, - inputSchema?: Schema, - outputSchema?: Schema - ): Promise; - - abstract serialize( - metadata?: GraphCombinedMetadata - ): Promise; - - abstract serializeNode(): Promise<[NodeDescriptor, GraphDescriptor?]>; -} - -export interface StateInterface { - queueUp(node: AbstractNode): void; - next(): AbstractNode; - done(): boolean; - - processResult(node: AbstractNode, result: OutputValues): OutputDistribution; - - missingInputs(node: AbstractNode): string[] | false; - shiftInputs(node: AbstractNode): I; - distributeResults(edge: EdgeInterface, inputs: InputValues): string[]; -} - -export interface OutputDistribution { - nodes: { - node: AbstractNode; - received: string[]; - missing: string[] | false; - }[]; - unused: string[]; -} - -export interface InvokeCallbacks { - // Called at the top of any iteration. - // Return true to abort execution. - // Use `state` to continue later. - stop?: ( - scope: ScopeInterface, - state: StateInterface - ) => boolean | Promise; - - // Called before a node is invoked. - // Waits for execution until promise is resolved. (Useful to pause execution) - // Return outputs values to skip invocation and use those values instead. - before?: ( - scope: ScopeInterface, - node: AbstractNode, - inputs: InputValues - ) => undefined | Promise; - - // Called after a node is invoked. - // Contains information useful for debugging. - // Does _not_ wait for promise to resolve before continuing execution. - after?: ( - scope: ScopeInterface, - node: AbstractNode, - inputs: InputValues, - outputs: OutputValues, - distribution: OutputDistribution - ) => void | Promise; - - // Called after a graph is done executing. - // Only called on the scope that the callback was added to. - done?: () => void | Promise; -} - -export interface ScopeConfig { - lexicalScope?: ScopeInterface; - dynamicScope?: ScopeInterface; -} - -export interface ScopeInterface { - parentLexicalScope?: ScopeInterface; - parentDynamicScope?: ScopeInterface; - - /** - * Add handlers to this scope. See `getHandler` for resolution order. - * - * @param handlers handlers to add - */ - addHandlers(handlers: NodeHandlers): void; - - /** - * Finds handler by name - * - * Scans up the parent chain if not found in this scope, looking in calling - * scopes before the declaration context scopes. - * - * That is, if a graph is invoked with a specific set of kits, then those kits - * have precedence over kits declared when building the graphs. And kits - * declared by invoking graphs downstream have precedence over those declared - * upstream. - * - * @param name Name of the handler to retrieve - * @returns Handler or undefined - */ - getHandler< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, - >( - name: string - ): NodeHandler | undefined; - - /** - * Pins a node to this scope, meaning it will be invoked/serialized for - * invoke() and serialize() unless those are called with specific nodes. - * - * Note that while all nodes are created within a scope, the scope is not by - * default aware of them. If nodes are created and nothing references them, - * then they are garbage collected. - * - * So there are two ways to reference graphs: - * - keep a reference to any node of the graph, then pass it to invoke() or - * serialize(). This is especially useful in the root scope. - * - create a graph, then pin it to the scope, and from then on refer to that - * scope when referring to a graph. This maps the mental model of nested - * scopes that define graphs. This also allows refering to a set of - * disjoint graphs (in the same scope). - * - * @param node node to pin to this scope - */ - pin< - I extends InputValues = InputValues, - O extends OutputValues = OutputValues, - >( - node: AbstractNode - ): void; - - /** - * Reduces set of pinned pins to one per disjoint graph. Call this after - * constructing a graph that might have pinned several nodes. - */ - compactPins(): void; - - /** - * Returns all pinned nodes in this scope. After calling compactPins(), this - * will return one node representing each disjoint graph. - * - * @returns Array of pinned nodes - */ - getPinnedNodes(): AbstractNode[]; - - /** - * Invokes a node, or all pinned nodes if none is specified. - * - * @param node Node to invoke, or undefined to invoke all pinned nodes - * @returns Promise that resolves when all nodes have been invoked - */ - invoke(node?: AbstractNode, state?: StateInterface): Promise; - - /** - * Helper to invoke a graph and return the values of the first `output` node - * that is being invoked. - * - * @param inputs Inputs to be passed to `input` node - * @param node Node to invoke, or undefined to invoke all pinned nodes - * - * @throws If no output node was called before graph terminates - */ - invokeOneRound( - inputs: InputValues, - node?: AbstractNode, - state?: StateInterface - ): Promise; - - /** - * Adds callbacks that are being called before and after each node invocation - * and once execution is done. - * - * `abort`, `before` and `after` will be called in invoked subgraphs as well. - * `done` only for scope that the callback was added to. - * - * @param callbacks Callbacks to add to the scope - */ - addCallbacks(callbacks: InvokeCallbacks): void; - - /** - * Serializes a node, or all pinned nodes if none is specified. - * - * @param metadata Metadata to be added to serialized graph - * @param node Node to serialize, or undefined to serialize all pinned nodes - */ - serialize( - metadata?: GraphCombinedMetadata, - node?: AbstractNode - ): Promise; -} diff --git a/packages/breadboard/src/node.ts b/packages/breadboard/src/node.ts deleted file mode 100644 index e12093ccb5e..00000000000 --- a/packages/breadboard/src/node.ts +++ /dev/null @@ -1,167 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - Edge, - NodeConfiguration, - NodeDescriptor, - NodeTypeIdentifier, - InputValues, - OutputValues, - Kit, - Breadboard, - BreadboardNode, - NodeConfigurationConstructor, -} from "./types.js"; -import { IdVendor } from "./id.js"; - -export type PartialEdge = { - out?: string; - in?: string; - optional?: boolean; - constant?: boolean; -}; - -type ParsedSpec = { - ltr: boolean; - edge?: PartialEdge; -}; - -const specRegex = /^((?.*)(?<-|->))?(?[^(.|?)]*)(?\.|\?)?$/m; - -type RegexGroups = { - a?: string; - b?: string; - dir?: string; - q?: string; -}; - -/** - * Parses a given string according to the following grammar: - * *|[{out}[->{in}][?|.]] - * - if "*" is specified, this is all-value wiring. All available output values - * will pass through this edge as input values. - * - if "out" is not specified, this is an empty string, which means control-only - * edge. No data passes through this edge. - * - if "in" is not specified, "in" is assumed to be of the same value - * as "out". - * - if "?" is specified, this is an optional edge. - * - if "." is specified, this is a constant edge. - */ -export const parseSpec = (spec: string): ParsedSpec => { - const result: ParsedSpec = { ltr: true }; - const match = spec.match(specRegex); - if (!match) throw new Error(`Invalid edge spec: ${spec}`); - const { a, b, dir, q } = match?.groups as RegexGroups; - const ltr = dir !== "<-"; - result.ltr = ltr; - const optional = q === "?"; - const constant = q === "."; - result.edge = {}; - if (constant) result.edge.constant = true; - if (optional) result.edge.optional = true; - if (!a && !b) return result; - if (a === "*" || b === "*") { - result.edge.out = "*"; - return result; - } - if (!a) { - result.edge.out = b; - result.edge.in = b; - return result; - } - if (!b) { - result.edge.out = a; - result.edge.in = a; - return result; - } - if (ltr) { - result.edge.out = a; - result.edge.in = b; - } else { - result.edge.out = b; - result.edge.in = a; - } - return result; -}; - -const nodeIdVendor = new IdVendor(); - -export const hasValues = (configuration: NodeConfigurationConstructor) => { - return Object.values(configuration).length > 0; -}; - -export class Node implements BreadboardNode { - #descriptor: NodeDescriptor; - #breadboard: Breadboard; - - constructor( - breadboard: Breadboard, - kit: Kit | undefined, - type: NodeTypeIdentifier, - configuration?: NodeConfigurationConstructor, - id?: string - ) { - this.#breadboard = breadboard.currentBoardToAddTo(); - this.#descriptor = { - id: id ?? nodeIdVendor.vendId(this.#breadboard, type), - type, - }; - - if (configuration && hasValues(configuration)) { - // For convenience we allow passing nodes as configuration, which are - // instead turned into constant incoming wires behind the scenes. - const incomingWiresToAdd = Object.entries(configuration).filter( - ([_, value]) => value instanceof Node - ) as unknown as [string, Node][]; - for (const [wire, from] of incomingWiresToAdd) { - delete configuration[wire]; - if (wire.indexOf("->") !== -1) - throw Error("Cannot pass output wire in confdig"); - this.wire(wire.indexOf("<-") === -1 ? `${wire}<-.` : wire, from); - } - - this.#descriptor.configuration = configuration as NodeConfiguration; - } - - this.#breadboard.addNode(this.#descriptor); - } - - wire( - spec: string, - to: BreadboardNode - ): BreadboardNode { - const { ltr, edge } = parseSpec(spec); - - const [fromNode, toNode] = ltr - ? [this, to as Node] - : [to as Node, this]; - const result: Edge = { - from: fromNode.#descriptor.id, - to: toNode.#descriptor.id, - ...edge, - }; - - if (fromNode.#breadboard !== toNode.#breadboard) { - // Note edge on the target board, which is the only currently supported - // version. Board.lambda() will use this to create a constant wire from - // the input node to this node, and from fromNode to the lambda node in - // the parent context, recursively if necessary. - toNode.#breadboard.addEdgeAcrossBoards( - result, - fromNode.#breadboard, - toNode.#breadboard - ); - } else { - this.#breadboard.addEdge(result); - } - return this; - } - - get id() { - return this.#descriptor.id; - } -} diff --git a/packages/breadboard/src/remote/chunk-repair.ts b/packages/breadboard/src/remote/chunk-repair.ts deleted file mode 100644 index d3c2ca94d9a..00000000000 --- a/packages/breadboard/src/remote/chunk-repair.ts +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -const getCompleteChunks = (pending: string, chunk: string) => { - const asString = `${pending}${chunk}`; - return asString.split("\n\n").filter(Boolean); -}; - -/** - * When processing HTTP responses, the server may send chunks that are - * broken in two ways: - * - Multiple chunks might be merged together - * - A single chunk might be broken into multiple chunks. - * - * This transform stream repairs such chunks, merging broken chunks and - * splitting merged chunks. - * - * @returns The transform stream that repaired chunks. - */ -export const chunkRepairTransform = () => { - let brokenChunk: string | null = null; - // Four variants of chunk breakage: - // 0. o | o -- no breakage. There aren't pending chunks, and the current - // chunk is fine. - // 1. x | o -- the current chunk looks fine, but it's actually the completion - // of a previous broken chunk. - // 2. o | x -- the current chunk is broken, and the next chunk will complete - // it. - // 3. x | x -- both the current chunk and the next chunk are broken. Here, - // the two chunks likely have a complete chunk somewhere in the middle - // (or not), yet there's a broken left-over chunk at the end. - return new TransformStream({ - transform(chunk, controller) { - const enqueue = (chunk: string) => { - controller.enqueue(`${chunk}\n\n`); - }; - - const missingEndMarker = !chunk.endsWith("\n\n"); - const chunks = chunk.split("\n\n"); - if (!missingEndMarker) { - chunks.pop(); - } - for (const [i, chunk] of chunks.entries()) { - const last = i === chunks.length - 1; - // Is this particular chunk broken? - const isBroken = last && missingEndMarker; - if (isBroken) { - if (brokenChunk !== null) { - // Variant 3: x | x - const completeChunks = getCompleteChunks(brokenChunk, chunk); - brokenChunk = completeChunks.pop() ?? null; - for (const completeChunk of completeChunks) { - enqueue(completeChunk); - } - } else { - // Variant 2: o | x - brokenChunk = chunk; - } - } else { - if (brokenChunk !== null) { - // Variant 1: x | o - const completeChunks = getCompleteChunks(brokenChunk, chunk); - for (const completeChunk of completeChunks) { - enqueue(completeChunk); - } - brokenChunk = null; - } else { - // Variant 0: o | o - enqueue(chunk); - } - } - } - }, - }); -}; diff --git a/packages/breadboard/src/remote/config.ts b/packages/breadboard/src/remote/config.ts deleted file mode 100644 index e17a75d8133..00000000000 --- a/packages/breadboard/src/remote/config.ts +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { DataStore } from "../data/types.js"; -import { Kit, NodeTypeIdentifier } from "../types.js"; - -/** - * A detailed specification for ProxyServer and ProxyClient. - * - * Example: - * ```js - * { - * node: "secrets", - * protect: { - * PALM_KEY: ["palm-generateText", "palm-embedText"], - * NODE_SPECIFIC_KEY: "specific-node-type", - * PINECONE_KEY: { - * receiver: "fetch", - * inputs: { - * url: /\.pinecone\.io\/, - * }, - * }, - * } - * } - * ``` - */ -export type NodeProxySpec = { - /** - * The node type to proxy. If specified, this node will be proxied. - * For ProxyClient, this means that the node will be part of a special kit - * that will proxy the inputs and outputs of the node to the ProxyServer. - * For ProxyServer, this means that the server will proxy this node. - */ - node: NodeTypeIdentifier; - /** - * If specified, describes the tunnels the outputs of the - * node. This is useful for protecting secrets that are generated by the - * node. - * - * This value is only used by the ProxyServer and is ignored by the - * ProxyClient. - * - * The spec is an object where the keys are the output names and the values - * are either: - * - A string -- the node type id that has access to the tunneled output. - * - An array of strings -- same as above, but a list of them. - * - A VaultMatchOutputs object -- a more detailed specification for - * tunneling the output, which includes differentiating by the content of - * a particular input of the node to which the tunnel leads. - * For example, if a node has an input called `url` and you want to - * tunnel only if the url matches a particular regex, you can - * specify: - * ```js - * { - * receiver: "fetch", - * inputs: { - * url: /\.pinecone\.io\/, - * }, - * } - * ``` - * - An array of VaultMatchOutputs objects -- same as above, but a - * list of them. - */ - tunnel?: TunnelSpec; -}; - -export type TunnelConstraints = { - [inputName: string]: string | TunnelConstraint; -}; - -export type TunnelConstraint = { - test(value: string): boolean; -}; - -export type TunnelDestinations = { - to: NodeTypeIdentifier; - when: TunnelConstraints; -}; - -export type TunnelSpec = { - [outputName: string]: - | TunnelDestinations - | TunnelDestinations[] - | string[] - | string; -}; - -export type NodeProxyConfig = (NodeTypeIdentifier | NodeProxySpec)[]; - -export type ProxyServerConfig = { - /** - * The kits to use to provide the handlers for the nodes that are proxied. - */ - kits: Kit[]; - /** - * The proxy configuration. This is an array of node types or node specs. - * @see NodeProxySpec for more details. - */ - proxy?: NodeProxyConfig; - /** - * The data store to use for storing data. - */ - store?: DataStore; -}; - -export const defineConfig = (config: ProxyServerConfig) => config; - -export const hasOrigin = (origin: string) => ({ - test: (url: string) => new URL(url).origin === origin, -}); diff --git a/packages/breadboard/src/remote/diagnostics-filter.ts b/packages/breadboard/src/remote/diagnostics-filter.ts deleted file mode 100644 index 1425b8cb703..00000000000 --- a/packages/breadboard/src/remote/diagnostics-filter.ts +++ /dev/null @@ -1,122 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { formatRunError } from "../harness/error.js"; -import type { RunDiagnosticsLevel } from "../harness/types.js"; -import { timestamp } from "../timestamp.js"; -import type { - EdgeResponse, - ErrorResponse, - GraphEndProbeData, - GraphStartProbeData, - InputResponse, - NodeEndResponse, - NodeStartResponse, - OutputResponse, - SkipProbeMessage, -} from "../types.js"; -import { End, RemoteMessage, RemoteMessageWriter } from "./types.js"; - -function omit(message: T, ...keys: (keyof T)[]): T { - const copy = { ...message }; - for (const key of keys) { - delete copy[key]; - } - return copy; -} - -type HasDescriptor = NodeStartResponse | NodeEndResponse; - -function noConfig(data: T): T { - const node = { ...data.node }; - delete node.configuration; - return { - ...data, - node, - }; -} - -function noIO(data: NodeEndResponse): NodeEndResponse { - const result = { ...data } as Partial; - delete result.inputs; - delete result.outputs; - return result as NodeEndResponse; -} - -export class DiagnosticsFilter { - #writer: RemoteMessageWriter; - #diagnostics: RunDiagnosticsLevel; - - constructor(writer: RemoteMessageWriter, diagnostics: RunDiagnosticsLevel) { - this.#writer = writer; - this.#diagnostics = diagnostics; - } - - #filterTop(pathLength: number) { - return this.#diagnostics === "top" && pathLength > 1; - } - - async writeGraphStart(data: GraphStartProbeData) { - if (this.#filterTop(data.path.length + 1)) { - return; - } - await this.#writer.write(["graphstart", omit(data, "graph")]); - } - - async writeGraphEnd(data: GraphEndProbeData) { - if (this.#filterTop(data.path.length + 1)) { - return; - } - await this.#writer.write(["graphend", data]); - } - - async writeNodeStart(data: NodeStartResponse) { - if (this.#filterTop(data.path.length)) { - return; - } - await this.#writer.write(["nodestart", noConfig(omit(data, "inputs"))]); - } - - async writeNodeEnd(data: NodeEndResponse) { - if (this.#filterTop(data.path.length)) { - return; - } - await this.#writer.write(["nodeend", noIO(noConfig(data))]); - } - - async writeSkip(_data: SkipProbeMessage["data"]) { - // Do not write skip messages to the server. - // await this.#writer.write(["skip", data]); - } - - async writeEdge(data: EdgeResponse) { - if (this.#diagnostics !== true) { - return; - } - await this.#writer.write(["edge", data]); - } - - async writeInput(data: InputResponse, next: string) { - await this.#writer.write(["input", data, next]); - } - - async writeOutput(data: OutputResponse) { - await this.#writer.write(["output", data]); - } - - async writeError(data: ErrorResponse) { - await this.#writer.write([ - "error", - { error: formatRunError(data.error), timestamp: timestamp() }, - ]); - } - - async writeEnd(data: End) { - if (this.#diagnostics) { - await this.#writer.write(["end", data]); - } - } -} diff --git a/packages/breadboard/src/remote/http.ts b/packages/breadboard/src/remote/http.ts deleted file mode 100644 index adf9fe15008..00000000000 --- a/packages/breadboard/src/remote/http.ts +++ /dev/null @@ -1,275 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - PatchedReadableStream, - parseWithStreams, - patchReadableStream, - stringifyWithStreams, -} from "../stream.js"; -import { - ClientBidirectionalStream, - ClientTransport, - ServerBidirectionalStream, - ServerTransport, -} from "./types.js"; - -/** - * Minimal interface in the shape of express.js's request object. - */ -export type ServerRequest = { - body: Request; -}; - -/** - * Minimal interface in the shape of express.js's response object. - */ -export type ServerResponse = { - header(field: string, value: string): unknown; - write: (chunk: unknown) => boolean; - end: () => unknown; -}; - -const isIterable = (o: unknown): boolean => { - return typeof o === "object" && o !== null && Symbol.iterator in o; -}; - -export const serverStreamEventDecoder = () => { - return new TransformStream({ - transform(chunk, controller) { - if (chunk.startsWith("data: ")) { - controller.enqueue(chunk.slice(6)); - } - }, - }); -}; - -export const parseWithStreamsTransform = () => { - const siphon = new TransformStream(); - const writer = siphon.writable.getWriter(); - return new TransformStream({ - transform(chunk, controller) { - const parsed = parseWithStreams(chunk, (id) => { - if (id !== 0) { - throw new Error( - "HTTPClientTransport does not support multiple streams at the moment." - ); - } - return siphon.readable; - }); - // Siphon away chunks into the stream. - const [type] = Array.isArray(parsed) ? parsed : []; - if (type === "http-stream-chunk") { - writer.write(parsed[1].chunk); - } else if (type === "http-stream-end") { - writer.close(); - } else { - controller.enqueue(parsed as Response); - } - }, - }); -}; - -export class HTTPServerTransport - implements ServerTransport -{ - #request: ServerRequest; - #response: ServerResponse; - - constructor(request: ServerRequest, response: ServerResponse) { - this.#request = request; - this.#response = response; - } - - createServerStream(): ServerBidirectionalStream { - const request = this.#request; - const response = this.#response; - patchReadableStream(); - response.header("Content-Type", "text/event-stream"); - return { - readableRequests: new ReadableStream({ - start(controller) { - if (!isIterable(request.body)) { - controller.error( - new Error( - "Unexpected uniterable body. This is likely a result of processing a GET request. Only POST requests are supported." - ) - ); - return; - } - controller.enqueue(request.body); - controller.close(); - }, - }) as PatchedReadableStream, - writableResponses: new WritableStream({ - async write(chunk) { - const stringified = stringifyWithStreams(chunk); - response.write(`data: ${stringified.value}\n\n`); - if (stringified.streams.length) { - if (stringified.streams.length > 1) { - throw new Error( - "HTTPServerTransport does not support multiple streams at the moment." - ); - } - // this chunk has streams, let's send the stream data - // along with the chunk. - const stream = stringified.streams[0]; - await stream.pipeTo( - new WritableStream({ - write(chunk) { - const data = ["http-stream-chunk", { chunk }]; - response.write(`data: ${JSON.stringify(data)}\n\n`); - }, - close() { - const data = ["http-stream-end", {}]; - response.write(`data: ${JSON.stringify(data)}\n\n`); - }, - }) - ); - } - }, - close() { - response.end(); - }, - }), - }; - } -} - -export type HTTPClientTransportOptions = RequestInit & { - fetch?: typeof globalThis.fetch; -}; - -/** - * This is an older version of the chunk repair transform that - * eventually needs to be deleted. - * - * It is not used by the modern remote runner machinery. - * - * When processing HTTP responses, the server may send chunks that are - * broken in two ways: - * - Multiple chunks might be merged together - * - A single chunk might be broken into multiple chunks. - * - * This transform stream repairs such chunks, merging broken chunks and - * splitting merged chunks. - * - * @returns The transform stream that repaired chunks. - */ -const chunkRepairTransform = () => { - let queue: string[] = []; - return new TransformStream({ - transform(chunk, controller) { - const brokenChunk = !chunk.endsWith("\n"); - const chunks = chunk.split("\n").filter(Boolean); - // If there are items in the queue, prepend them to the first chunk - // and enqueue the result. - if (queue.length && !brokenChunk) { - controller.enqueue(`${queue.join("")}${chunks.shift()}`); - queue = []; - } - // Queue all chunks except the last one. - while (chunks.length > 1) { - controller.enqueue(chunks.shift()); - } - const lastChunk = chunks.shift(); - if (!lastChunk) return; - - if (brokenChunk) { - queue.push(lastChunk); - } else { - controller.enqueue(lastChunk); - } - }, - flush() { - // The queue should be empty at the end of the stream. - // The presence of items in the queue is an indication that the - // stream was not formatted correctly. - if (queue.length) { - throw new Error("Unexpected end of stream."); - } - }, - }); -}; - -export class HTTPClientTransport - implements ClientTransport -{ - #url: string; - #options: HTTPClientTransportOptions; - #fetch: typeof globalThis.fetch; - - constructor(url: string, options?: HTTPClientTransportOptions) { - this.#url = url; - this.#options = { - ...options, - method: "POST", - credentials: "include", - }; - this.#fetch = this.#options.fetch ?? globalThis.fetch.bind(globalThis); - } - - createClientStream(): ClientBidirectionalStream { - let responseResolve: - | undefined - | ((response: PatchedReadableStream) => void); - const responsePromise: Promise> = - new Promise((resolve) => { - responseResolve = resolve; - }); - - // eslint-disable-next-line @typescript-eslint/no-this-alias - const that = this; - return { - readableResponses: new ReadableStream({ - async pull(controller) { - const response = await responsePromise; - const reader = response.getReader(); - for (;;) { - const result = await reader.read(); - if (result.done) { - break; - } else { - console.log( - "%cServer-Sent Event Chunk", - "background: #009; color: #FFF", - result.value - ); - controller.enqueue(result.value as Response); - } - } - controller.close(); - }, - }) as PatchedReadableStream, - writableRequests: new WritableStream({ - async write(chunk, controller) { - if (!responseResolve) { - throw new Error( - "HTTPClientTransport supports only one write per stream instance." - ); - } - const response = await that.#fetch(that.#url, { - ...that.#options, - body: JSON.stringify(chunk), - }); - if (!response.ok) { - controller.error(new Error(`HTTP error: ${response.status}`)); - } - responseResolve( - response.body - ?.pipeThrough(new TextDecoderStream()) - .pipeThrough(chunkRepairTransform()) - .pipeThrough(serverStreamEventDecoder()) - .pipeThrough( - parseWithStreamsTransform() - ) as PatchedReadableStream - ); - responseResolve = undefined; - }, - }), - }; - } -} diff --git a/packages/breadboard/src/remote/index.ts b/packages/breadboard/src/remote/index.ts deleted file mode 100644 index d94a28bf359..00000000000 --- a/packages/breadboard/src/remote/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export { HTTPServerTransport, HTTPClientTransport } from "./http.js"; -export { - PortDispatcher, - WorkerServerTransport, - WorkerClientTransport, -} from "./worker.js"; -export { ProxyServer, ProxyClient } from "./proxy.js"; -export { RunServer, RunClient } from "./run.js"; -export { InitServer, InitClient } from "./init.js"; -export { defineConfig, hasOrigin, type ProxyServerConfig } from "./config.js"; -export type * from "./types.js"; -export type * from "./config.js"; -export type * from "./http.js"; -export { handleRunGraphRequest } from "./run-graph-server.js"; diff --git a/packages/breadboard/src/remote/init.ts b/packages/breadboard/src/remote/init.ts deleted file mode 100644 index 50ce7b6a6c1..00000000000 --- a/packages/breadboard/src/remote/init.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - ClientTransport, - LoadRequest, - LoadResponse, - ServerTransport, -} from "./types.js"; - -export class InitServer { - #transport: ServerTransport; - - constructor(transport: ServerTransport) { - this.#transport = transport; - } - - async serve() { - const stream = this.#transport.createServerStream(); - const reader = stream.readableRequests.getReader(); - const request = await reader.read(); - if (request.done) { - throw new Error("Client closed stream without sending a request."); - } - return request.value.url; - } -} - -export class InitClient { - #transport: ClientTransport; - - constructor(transport: ClientTransport) { - this.#transport = transport; - } - - async load(url: string) { - const stream = this.#transport.createClientStream(); - const writer = stream.writableRequests.getWriter(); - await writer.write({ url }); - await writer.close(); - } -} diff --git a/packages/breadboard/src/remote/proxy.ts b/packages/breadboard/src/remote/proxy.ts deleted file mode 100644 index ccc49f8b6bb..00000000000 --- a/packages/breadboard/src/remote/proxy.ts +++ /dev/null @@ -1,217 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { callHandler, handlersFromKits } from "../handler.js"; -import { streamsToAsyncIterable } from "../stream.js"; -import { asRuntimeKit } from "../kits/ctors.js"; -import { KitBuilder } from "../kits/builder.js"; -import { - ErrorResponse, - InputValues, - NodeDescriptor, - NodeHandlerContext, - OutputValues, -} from "../types.js"; -import { NodeProxyConfig, NodeProxySpec, ProxyServerConfig } from "./config.js"; -import { - AnyProxyRequestMessage, - AnyProxyResponseMessage, - ClientTransport, - ServerTransport, -} from "./types.js"; -import { createTunnelKit, readConfig } from "./tunnel.js"; -import { timestamp } from "../timestamp.js"; -import { inflateData } from "../data/inflate-deflate.js"; - -type ProxyServerTransport = ServerTransport< - AnyProxyRequestMessage, - AnyProxyResponseMessage ->; - -const getHandlerConfig = ( - type: string, - config: NodeProxyConfig = [] -): NodeProxySpec | undefined => { - const handlerConfig = config.find((arg) => { - if (typeof arg === "string") return arg === type; - else return arg.node === type; - }); - if (typeof handlerConfig === "string") { - return { - node: handlerConfig, - }; - } - return handlerConfig; -}; - -const makeSerializable = (data: OutputValues) => { - if (data["$error"]) { - const error = data["$error"] as ErrorResponse; - error.error = - error.error instanceof Error ? error.error.message : error.error; - } - return data; -}; - -export class ProxyServer { - #transport: ProxyServerTransport; - - constructor(transport: ProxyServerTransport) { - this.#transport = transport; - } - - async serve(config: ProxyServerConfig) { - const { kits, store } = config; - const stream = this.#transport.createServerStream(); - const tunnelKit = createTunnelKit( - readConfig(config), - handlersFromKits(kits) - ); - const handlers = tunnelKit.handlers; - - for await (const request of streamsToAsyncIterable( - stream.writableResponses, - stream.readableRequests - )) { - const [type] = request.data; - - if (type === "end") { - break; - } - - if (type !== "proxy") { - request.reply([ - "error", - { error: "Expected proxy request.", timestamp: timestamp() }, - ]); - continue; - } - - const [, { node, inputs }] = request.data; - const handlerConfig = getHandlerConfig(node.type, config.proxy); - - const handler = handlerConfig ? handlers[node.type] : undefined; - if (!handler) { - request.reply([ - "error", - { - error: "Can't proxy a node of this node type.", - timestamp: timestamp(), - }, - ]); - continue; - } - - try { - const result = await callHandler(handler, inputs, { - descriptor: node, - store, - }); - - if (!result) { - request.reply([ - "error", - { error: "Handler returned nothing.", timestamp: timestamp() }, - ]); - continue; - } - const outputs = store - ? ((await inflateData( - store, - makeSerializable(result) - )) as OutputValues) - : result; - request.reply(["proxy", { outputs }]); - } catch (e) { - request.reply([ - "error", - { error: (e as Error).message, timestamp: timestamp() }, - ]); - } - } - } -} - -type ProxyClientTransport = ClientTransport< - AnyProxyRequestMessage, - AnyProxyResponseMessage ->; - -export class ProxyClient { - #transport: ProxyClientTransport; - - constructor(transport: ProxyClientTransport) { - this.#transport = transport; - } - - shutdownServer() { - const stream = this.#transport.createClientStream(); - const writer = stream.writableRequests.getWriter(); - writer.write(["end", { timestamp: timestamp() }]); - writer.close(); - } - - async proxy( - node: NodeDescriptor, - inputs: InputValues, - context: NodeHandlerContext - ): Promise { - const stream = this.#transport.createClientStream(); - const writer = stream.writableRequests.getWriter(); - const reader = stream.readableResponses.getReader(); - - const store = context.store; - inputs = store - ? ((await inflateData(store, inputs)) as InputValues) - : inputs; - - writer.write(["proxy", { node, inputs }]); - writer.close(); - - const result = await reader.read(); - if (result.done) - throw new Error("Unexpected proxy failure: empty response."); - - const [type] = result.value; - if (type === "proxy") { - const [, { outputs }] = result.value; - return outputs; - } else if (type === "error") { - const [, { error }] = result.value; - throw new Error(JSON.stringify(error)); - } else { - throw new Error( - `Unexpected proxy failure: unknown response type "${type}".` - ); - } - } - - createProxyKit(args: NodeProxyConfig = []) { - const nodesToProxy = args.map((arg) => { - if (typeof arg === "string") return arg; - else return arg.node; - }); - const proxiedNodes = Object.fromEntries( - nodesToProxy.map((type) => { - return [ - type, - { - invoke: async ( - inputs: InputValues, - context: NodeHandlerContext - ) => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const descriptor = context.descriptor!; - const result = await this.proxy(descriptor, inputs, context); - return result; - }, - }, - ]; - }) - ); - return asRuntimeKit(new KitBuilder({ url: "proxy" }).build(proxiedNodes)); - } -} diff --git a/packages/breadboard/src/remote/run-graph-server.ts b/packages/breadboard/src/remote/run-graph-server.ts deleted file mode 100644 index 4219ea518fc..00000000000 --- a/packages/breadboard/src/remote/run-graph-server.ts +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { ServerRunConfig, ServerRunRequest } from "./types.js"; -import { run } from "../harness/run.js"; -import { OutputValues } from "../types.js"; -import { timestamp } from "../timestamp.js"; -import { createRunStateManager } from "../run/index.js"; -import { inflateData } from "../data/inflate-deflate.js"; -import { DiagnosticsFilter } from "./diagnostics-filter.js"; - -export const handleRunGraphRequest = async ( - request: ServerRunRequest, - config: ServerRunConfig -): Promise => { - const { - url, - kits, - writer, - loader, - dataStore, - stateStore, - inputs: defaultInputs, - graph, - } = config; - const { next, inputs, diagnostics = false } = request; - - let inputsToConsume = next ? undefined : inputs; - - const resumeFrom = await stateStore?.load(next); - - const state = createRunStateManager(resumeFrom, inputs); - - const runner = run({ - runner: graph, - url, - kits, - loader, - store: dataStore, - inputs: defaultInputs, - interactiveSecrets: false, - diagnostics, - state, - }); - - const filter = new DiagnosticsFilter(writer, diagnostics); - - for await (const result of runner) { - const { type, data, reply } = result; - switch (type) { - case "graphstart": { - await filter.writeGraphStart(data); - break; - } - case "graphend": { - await filter.writeGraphEnd(data); - break; - } - case "nodestart": { - await filter.writeNodeStart(data); - break; - } - case "nodeend": { - await filter.writeNodeEnd(data); - break; - } - case "skip": { - await filter.writeSkip(data); - break; - } - case "edge": { - await filter.writeEdge(data); - break; - } - case "input": { - if (inputsToConsume && Object.keys(inputsToConsume).length > 0) { - await reply({ inputs: inputsToConsume }); - inputsToConsume = undefined; - break; - } else { - const reanimationState = state.lifecycle().reanimationState(); - const next = await stateStore.save(reanimationState); - await filter.writeInput(data, next); - await writer.close(); - return; - } - } - case "output": { - const outputs = (await inflateData( - dataStore, - data.outputs - )) as OutputValues; - await filter.writeOutput({ ...data, outputs }); - break; - } - case "error": { - await filter.writeError(data); - await writer.close(); - return; - } - case "end": { - await filter.writeEnd(data); - await writer.close(); - return; - } - default: { - console.log("Unknown type", type, data); - } - } - } - await writer.write([ - "error", - { - error: "Run completed without signaling end or error.", - timestamp: timestamp(), - }, - ]); -}; diff --git a/packages/breadboard/src/remote/run.ts b/packages/breadboard/src/remote/run.ts deleted file mode 100644 index 7b948e08c15..00000000000 --- a/packages/breadboard/src/remote/run.ts +++ /dev/null @@ -1,165 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Diagnostics } from "../harness/diagnostics.js"; -import { extractError } from "../harness/error.js"; -import { createRunStateManager } from "../run/index.js"; -import { runGraph } from "../run/run-graph.js"; -import { RunState } from "../run/types.js"; -import { - WritableResult, - streamsToAsyncIterable, - stubOutStreams, -} from "../stream.js"; -import { timestamp } from "../timestamp.js"; -import { - GraphDescriptor, - InputValues, - NodeHandlerContext, - OutputValues, -} from "../types.js"; -import { - AnyClientRunResult, - AnyRunRequestMessage, - RemoteMessage, - InputResolveRequest, - RunClientTransport, - RunRequestMessage, - ServerTransport, -} from "./types.js"; - -type RunServerTransport = ServerTransport; - -export class RunServer { - #transport: RunServerTransport; - - constructor(transport: RunServerTransport) { - this.#transport = transport; - } - - async serve( - runner: GraphDescriptor, - diagnostics = false, - context: NodeHandlerContext = {} - ) { - const stream = this.#transport.createServerStream(); - const requestReader = stream.readableRequests.getReader(); - let request = await requestReader.read(); - if (request.done) return; - - const responses = stream.writableResponses.getWriter(); - - const servingContext: NodeHandlerContext = { - ...context, - state: createRunStateManager(), - probe: diagnostics - ? new Diagnostics(async (message) => { - const { type, data } = message; - const response = [type, stubOutStreams(data)]; - if (type == "nodestart") { - response.push(message.state); - } - await responses.write(response as RemoteMessage); - }) - : undefined, - }; - - try { - for await (const stop of runGraph(runner, servingContext)) { - if (stop.type === "input") { - const { node, inputArguments, timestamp, path, invocationId } = stop; - const bubbled = invocationId == -1; - await responses.write([ - "input", - { node, inputArguments, timestamp, path, bubbled }, - ]); - request = await requestReader.read(); - if (request.done) { - await responses.close(); - return; - } else { - const [type, inputs] = request.value; - if (type === "input") { - stop.inputs = inputs.inputs; - } - } - } else if (stop.type === "output") { - const { node, outputs, timestamp, path, invocationId } = stop; - const bubbled = invocationId == -1; - await responses.write([ - "output", - { node, outputs, timestamp, path, bubbled }, - ]); - } - } - await responses.write(["end", { timestamp: timestamp() }]); - await responses.close(); - } catch (e) { - const error = extractError(e); - console.error("Run Server error:", error); - await responses.write(["error", { error, timestamp: timestamp() }]); - await responses.close(); - } - } -} - -const createRunResult = ( - response: WritableResult -): AnyClientRunResult => { - const [type, data, state] = response.data; - const reply = async (chunk: AnyRunRequestMessage[1]) => { - if (type !== "input") { - throw new Error( - "For now, we cannot reply to messages other than 'input'." - ); - } - await response.reply([type, chunk as InputResolveRequest]); - }; - return { - type, - data, - state, - reply, - } as AnyClientRunResult; -}; - -export class RunClient { - #transport: RunClientTransport; - - constructor(clientTransport: RunClientTransport) { - this.#transport = clientTransport; - } - - async *run(state?: RunState): AsyncGenerator { - const stream = this.#transport.createClientStream(); - const server = streamsToAsyncIterable( - stream.writableRequests, - stream.readableResponses - ); - const request = ["run", {}] as RunRequestMessage; - state && request.push(state); - await server.start(request); - for await (const response of server) { - yield createRunResult(response); - } - } - - async runOnce(inputs: InputValues): Promise { - let outputs; - - for await (const stop of this.run()) { - const { type, data } = stop; - if (type === "input") { - stop.reply({ inputs }); - } else if (type === "output") { - outputs = data.outputs; - break; - } - } - - return outputs || {}; - } -} diff --git a/packages/breadboard/src/remote/tunnel.ts b/packages/breadboard/src/remote/tunnel.ts deleted file mode 100644 index 367ae52d037..00000000000 --- a/packages/breadboard/src/remote/tunnel.ts +++ /dev/null @@ -1,358 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { callHandler } from "../handler.js"; -import { - InputValues, - Kit, - NodeHandlerContext, - NodeHandlers, - NodeTypeIdentifier, - NodeValue, - OutputValues, -} from "../types.js"; -import { - ProxyServerConfig, - TunnelDestinations, - TunnelConstraints, - TunnelSpec, -} from "./config.js"; - -/** - * Polyfill for atob and btoa. - */ -export const atob = globalThis.process - ? (str: string) => Buffer.from(str, "base64").toString("binary") - : globalThis.atob; -export const btoa = globalThis.process - ? (str: string) => Buffer.from(str, "binary").toString("base64") - : globalThis.btoa; - -const TUNNEL_VALUE_SEPARATOR = "~"; - -/** - * All tunnels defined for a particular node (the tunnel entry). - */ -export type NodeTunnels = { - [outputName: string]: NodeTunnel[]; -}; - -/** - * The map of the entire network of tunnels for all nodes. - */ -export type TunnelMap = { - [node: NodeTypeIdentifier]: NodeTunnels; -}; - -export type TunnelDestinationMap = { - [destinationNode: NodeTypeIdentifier]: NodeTunnel[]; -}; - -export class NodeTunnel implements TunnelDestinations { - constructor( - readonly outputName: string, - readonly from: NodeTypeIdentifier, - readonly to: NodeTypeIdentifier, - readonly when: TunnelConstraints = {} - ) {} - - getInputNames() { - const inputNames = Object.keys(this.when); - return inputNames.length === 0 ? [this.outputName] : inputNames; - } - - matches(inputs: InputValues) { - return Object.entries(this.when).every(([inputName, value]) => { - const inputValue = inputs[inputName]; - if (typeof value === "string") { - return inputValue === value; - } else { - if (typeof inputValue !== "string") return false; - return value.test(inputValue); - } - }); - } -} - -export const readConfig = (config: ProxyServerConfig): TunnelMap => { - if (!config.proxy) return {}; - return Object.fromEntries( - config.proxy - .map((spec) => { - if (typeof spec === "string") { - return undefined; - } - if (!spec.tunnel) return undefined; - return [spec.node, readNodeSpec(spec.node, spec.tunnel)]; - }) - .filter(Boolean) as [NodeTypeIdentifier, NodeTunnels][] - ); -}; - -export const readNodeSpec = ( - node: NodeTypeIdentifier, - spec: TunnelSpec -): NodeTunnels => { - return Object.fromEntries( - Object.entries(spec).map(([outputName, value]) => { - if (typeof value === "string") { - return [outputName, [new NodeTunnel(outputName, node, value)]]; - } else if (Array.isArray(value)) { - return [ - outputName, - value.map((v) => { - if (typeof v === "string") { - return new NodeTunnel(outputName, node, v); - } - return new NodeTunnel(outputName, node, v.to, v.when); - }), - ]; - } else { - return [ - outputName, - [new NodeTunnel(outputName, node, value.to, value.when)], - ]; - } - }) - ); -}; - -type OutputReplacer = (outputName: string, outputValue: NodeValue) => NodeValue; - -export const replaceOutputs = ( - outputs: void | OutputValues, - tunnels: NodeTunnels, - replacer: OutputReplacer -): void | OutputValues => { - if (!outputs) return; - return Object.fromEntries( - Object.entries(outputs).map(([outputName, value]) => { - return outputName in tunnels - ? [outputName, replacer(outputName, value)] - : [outputName, value]; - }) - ); -}; - -type InputReplacer = ( - inputValue: NodeValue, - allow: boolean -) => Promise; - -export const replaceInputs = async ( - inputs: InputValues, - tunnels: NodeTunnel[], - replacer: InputReplacer -) => { - // Decide if we should allow or block values for this node. - const allow = tunnels.some((tunnel) => tunnel.matches(inputs)); - - return Object.fromEntries( - await Promise.all( - Object.entries(inputs).map(async ([inputName, value]) => { - return [inputName, await replacer(value, allow)]; - }) - ) - ); -}; - -// Compute a simple hash that expires every 7 days. -// The point of this hash is not protect anything, but rather to have -// a simple way to identify a tunnelled value. -// It is also rotating so that the users of the node proxy don't accidentally -// adopt bad practices of hard-coding the values. -// Note: the rotation will occasionally cause errors at the break of the week. -// TODO: Fix the rotation to be window-based or come up with an even better -// solution. -const MILLISECONDS_IN_A_WEEK = 1000 * 60 * 60 * 24 * 7; -const TUNNEL_HASH = Math.round(Date.now() / MILLISECONDS_IN_A_WEEK).toString( - 36 -); -const TUNNEL_PREFIX = `T-${TUNNEL_HASH}-`; -const TUNNEL_SUFFIX = `-${TUNNEL_HASH}-T`; -const SPLIT_REGEX = new RegExp(`(${TUNNEL_PREFIX}.*?${TUNNEL_SUFFIX})`, "gm"); -const TUNNEL_REGEX = new RegExp(`^${TUNNEL_PREFIX}(.+?)${TUNNEL_SUFFIX}$`); -const BLOCKED_TUNNEL_VALUE = "VALUE_BLOCKED"; - -export const getTunnelValue = ( - nodeType: NodeTypeIdentifier, - outputName: string, - inputs: InputValues -) => { - const memoize = btoa(JSON.stringify(inputs)).replace("=", ""); - return `${TUNNEL_PREFIX}${nodeType}${TUNNEL_VALUE_SEPARATOR}${outputName}${TUNNEL_VALUE_SEPARATOR}${memoize}${TUNNEL_SUFFIX}`; -}; - -type TunnelScanResult = ( - | { - value: string; - } - | { - nodeType: NodeTypeIdentifier; - outputName: string; - inputs: string; - } -)[]; - -export const scanTunnelValue = (value: string): TunnelScanResult => { - const parts = value.split(SPLIT_REGEX).filter(Boolean); - return parts.map((part) => { - const match = part.match(TUNNEL_REGEX); - if (match) { - // This is a tunnel value, parse it into components and return - // a helper object that enables the caller to replace the value. - const value = match[1].split(TUNNEL_VALUE_SEPARATOR); - const [nodeType, outputName, encodedInputs] = value; - const inputs = atob(encodedInputs); - return { - nodeType, - outputName, - inputs, - }; - } else { - // This is a regular substring, return a helper object that handles - // joining it back together as a string. - return { - value: part, - }; - } - }); -}; - -type TunnelValueReplacer = ( - nodeType: NodeTypeIdentifier, - inputs: InputValues -) => Promise; - -export const replaceTunnelledInputs = async ( - input: NodeValue, - /** - * If true, the tunneled inputs will be replaced with the original value. - * If false, the tunneled inputs should be blocked. The tunnel value - * is replaced with a BLOCKED_TUNNEL_VALUE. - */ - allow: boolean, - replacer: TunnelValueReplacer -) => { - const json = JSON.stringify(input); - const parts = scanTunnelValue(json); - - const result = await Promise.all( - parts.map(async (part) => { - if ("inputs" in part) { - const inputs = JSON.parse(part.inputs); - const { nodeType, outputName } = part; - const outputs = allow - ? await replacer(nodeType, inputs) - : { [outputName]: BLOCKED_TUNNEL_VALUE }; - if (!outputs) return ""; - let jsonString = JSON.stringify(outputs[outputName]); - if (jsonString.startsWith('"')) { - jsonString = jsonString.slice(1, -1); - } - jsonString = JSON.stringify(jsonString); - return jsonString.slice(1, -1); - } - return part.value; - }) - ); - return JSON.parse(result.join("")); -}; - -export const createDestinationMap = (map: TunnelMap): TunnelDestinationMap => { - // pivot the map of tunnel entries to create a map of tunnel destinations - const entries = Object.entries(map).flatMap(([_, nodeTunnels]) => { - return Object.entries(nodeTunnels).flatMap(([_, tunnels]) => { - return tunnels.map((tunnel) => { - return [tunnel.to, tunnel]; - }); - }); - }) as [NodeTypeIdentifier, NodeTunnel][]; - // collate entries by destination node - return entries.reduce((acc, [to, tunnel]) => { - if (!acc[to]) acc[to] = []; - acc[to].push(tunnel); - return acc; - }, {} as TunnelDestinationMap); -}; - -/** - * A special kit that provides tunneling of outputs and inputs as specified - * by the Tunnels spec. - * - * This kit is constructed from existing NodeHandlers and the Tunnels spec. - * It reads the spec and wraps the node handlers to add the tunneling logic. - * - * The tunnel entries, or the outputs of nodes that are tunneled, are replaced - * with a special value that is computed from the node type and the output name. - * - * The tunnel destinations, or the inputs of the nodes to which a tunnel leads, are - * replaced with the original value of the tunnel entry. - */ -export const createTunnelKit = ( - map: TunnelMap, - handlers: NodeHandlers -): Kit => { - // wrap handlers to tunnel outputs (tunnel entries) - const outputWrappedHandlers = Object.fromEntries( - Object.entries(handlers).map(([nodeType, handler]) => { - const nodeTunnels = map[nodeType]; - if (!nodeTunnels) return [nodeType, handler]; - return [ - nodeType, - async (inputs: InputValues, context: NodeHandlerContext) => { - const outputs = await callHandler(handler, inputs, context); - return replaceOutputs(outputs, nodeTunnels, (name) => - getTunnelValue(nodeType, name, inputs) - ); - }, - ]; - }) - ); - - // wrap handlers to connect the tunnel to the inputs (tunnel destinations) - const destinations = createDestinationMap(map); - const inputWrappedHandlers = Object.fromEntries( - Object.entries(outputWrappedHandlers).map(([nodeType, handler]) => { - const destinationTunnels = destinations[nodeType]; - if (!destinationTunnels) return [nodeType, handler]; - return [ - nodeType, - async (inputs: InputValues, context: NodeHandlerContext) => { - return callHandler( - handler, - await replaceInputs( - inputs, - destinationTunnels, - async (value, allow) => { - // scan for tunneled values in `value`. - // for each found `tunnel value`, - // - extract the node type and output name of the tunnel entry. - // - call the handler of the node type for the tunnel entry - // with the inputs that are decoded from the tunnel value - // - from the outputs, extract the inputs that are tunneled - // and replace the `tunnel value` with them. - return replaceTunnelledInputs( - value, - allow, - async (nodeType, inputs) => { - return callHandler(handlers[nodeType], inputs, context); - } - ); - } - ), - context - ); - }, - ]; - }) - ); - - return { - url: "tunnel-kit", - handlers: inputWrappedHandlers, - }; -}; diff --git a/packages/breadboard/src/remote/types.ts b/packages/breadboard/src/remote/types.ts deleted file mode 100644 index fbda4333bbd..00000000000 --- a/packages/breadboard/src/remote/types.ts +++ /dev/null @@ -1,259 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { DataStore, StateStore } from "../data/types.js"; -import { RunConfig, RunDiagnosticsLevel } from "../harness/types.js"; -import { GraphLoader } from "../loader/types.js"; -import type { RunState } from "../run/types.js"; -import { PatchedReadableStream } from "../stream.js"; -import { - EdgeProbeMessage, - ErrorResponse, - GraphDescriptor, - GraphEndProbeMessage, - GraphStartProbeMessage, - InputResponse, - InputValues, - Kit, - NodeDescriptor, - NodeEndProbeMessage, - NodeStartProbeMessage, - OutputResponse, - OutputValues, - SkipProbeMessage, -} from "../types.js"; - -/** - * Sent by the client to request loading a board. This is an optional request - * that may not be implemented in some environments (for example, a cloud - * function that can only run one board). - */ -export type LoadRequest = { - /** - * The url of the board to load. - */ - url: string; -}; - -/** - * Sent by the server to indicate that the board is loaded. - */ -export type LoadResponse = { - /** - * The title of the graph. - */ - title?: string; - /** - * The description of the graph. - */ - description?: string; - /** - * Version of the graph. - * [semver](https://semver.org/) format is encouraged. - */ - version?: string; - /** - * The Mermaid diagram of the graph. - */ - diagram?: string; - /** - * The url of the graph. - */ - url?: string; - /** - * Information about the nodes in the graph. - */ - nodes?: NodeDescriptor[]; -}; - -type GenericResult = { type: string; data: unknown }; - -export type AsRemoteMessage = [ - T["type"], - T["data"], - next?: string, -]; - -/** - * A run request is an empty object. - * It basically just pokes the server to start running. - */ -export type RunRequest = Record; -export type RunRequestMessage = ["run", RunRequest, RunState?]; -export type OutputRemoteMessage = ["output", OutputResponse]; -export type InputRemoteMessage = ["input", InputResponse, next?: string]; - -/** - * Sent by the client to provide inputs, requested by the server. - */ -export type InputResolveRequest = { inputs: InputValues }; -export type InputResolveRequestMessage = [ - "input", - InputResolveRequest, - next?: string, -]; - -export type LastNode = { - node: NodeDescriptor; - missing: string[]; -}; - -/** - * Indicates that the board is done running. - * Can only be the last message in the response stream. - */ -export type End = { - timestamp: number; - last?: LastNode; -}; -export type EndRemoteMessage = ["end", End]; -export type EndRequestMessage = ["end", End]; - -export type ErrorRemoteMessage = ["error", ErrorResponse]; - -/** - * Sent by the client to request to proxy a node. - */ -export type ProxyRequest = { - /** - * The description of the node to be proxied. - * @see [NodeDescriptor] - */ - node: NodeDescriptor; - /** - * The input values that the board is providing to the node. - * @see [InputValues] - */ - inputs: InputValues; -}; - -/** - * Sent by the server to respond to respond with the proxy results. - */ -export type ProxyResponse = { - /** - * The output values that the host is providing to the board in lieu of - * the proxied node. - * @see [OutputValues] - */ - outputs: OutputValues; -}; - -export type ProxyRequestMessage = ["proxy", ProxyRequest]; -export type ProxyResponseMessage = ["proxy", ProxyResponse]; - -export type ProxyChunkResponse = { chunk: unknown }; -export type ProxyChunkResponseMessage = ["chunk", ProxyChunkResponse]; - -export type AnyProxyRequestMessage = ProxyRequestMessage | EndRequestMessage; -export type AnyProxyResponseMessage = - | ProxyResponseMessage - | ErrorRemoteMessage - | ProxyChunkResponseMessage - | EndRemoteMessage; - -export type AnyRunRequestMessage = - | RunRequestMessage - | InputResolveRequestMessage; - -export type NodeStartRemoteMessage = AsRemoteMessage; -export type NodeEndRemoteMessage = AsRemoteMessage; -export type GraphStartRemoteMessage = AsRemoteMessage; -export type GraphEndRemoteMessage = AsRemoteMessage; -export type SkipRemoteMessage = AsRemoteMessage; -export type EdgeRemoteMessage = AsRemoteMessage; - -export type DiagnosticsRemoteMessage = - | NodeStartRemoteMessage - | NodeEndRemoteMessage - | GraphStartRemoteMessage - | GraphEndRemoteMessage - | SkipRemoteMessage - | EdgeRemoteMessage; - -export type RemoteMessage = - | OutputRemoteMessage - | InputRemoteMessage - | EndRemoteMessage - | ErrorRemoteMessage - | DiagnosticsRemoteMessage; - -export type RemoteMessageWriter = WritableStreamDefaultWriter; -export type RemoteMessageWritableStream = WritableStream; - -export interface ClientBidirectionalStream { - writableRequests: WritableStream; - readableResponses: PatchedReadableStream; -} - -export interface ServerBidirectionalStream { - readableRequests: PatchedReadableStream; - writableResponses: WritableStream; -} - -export interface ServerTransport { - createServerStream(): ServerBidirectionalStream; -} - -export interface ClientTransport { - createClientStream(): ClientBidirectionalStream; -} - -export type RunClientTransport = ClientTransport< - AnyRunRequestMessage, - RemoteMessage ->; - -type ReplyFunction = { - reply: (chunk: AnyRunRequestMessage[1]) => Promise; -}; - -export type RunStateFunction = () => Promise; - -type ClientRunResultFromMessage = ResponseMessage extends [ - string, - object, - string?, -] - ? { - type: ResponseMessage[0]; - data: ResponseMessage[1]; - saveState?: RunStateFunction; - } & ReplyFunction - : never; - -export type AnyClientRunResult = ClientRunResultFromMessage; - -export type AnyProbeClientRunResult = - ClientRunResultFromMessage; - -export type ClientRunResult = T & ReplyFunction; - -export type ServerRunRequest = { - inputs?: InputValues; - next?: string; - diagnostics?: RunDiagnosticsLevel; -}; - -export type ServerRunConfig = { - graph?: GraphDescriptor; - url: string; - kits: Kit[]; - writer: RemoteMessageWriter; - loader: GraphLoader; - dataStore: DataStore; - stateStore: StateStore; - inputs?: InputValues; - diagnostics?: RunDiagnosticsLevel; -}; - -export type RemoteRunConfig = Omit; - -export type RemoteRunRequestBody = { - $key: string; - $next?: string; - $diagnostics?: boolean; -} & InputValues; diff --git a/packages/breadboard/src/remote/worker.ts b/packages/breadboard/src/remote/worker.ts deleted file mode 100644 index f145efd2efc..00000000000 --- a/packages/breadboard/src/remote/worker.ts +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - PatchedReadableStream, - PortStreams, - portFactoryToStreams, - portToStreams, - streamFromReader, - streamFromWriter, -} from "../stream.js"; -import { - ClientTransport, - ServerBidirectionalStream, - ServerTransport, -} from "./types.js"; - -const DISPATCHER_SEND = "port-dispatcher-sendport"; - -export class PortDispatcher { - #worker: Worker; - #waitForSender: Map void> = new Map(); - #pool: Map = new Map(); - - constructor(worker: Worker) { - this.#worker = worker; - this.#worker.addEventListener("message", (event) => { - const { type, id, port } = event.data; - if (type !== DISPATCHER_SEND) return; - const waiting = this.#waitForSender.get(id); - if (waiting) { - waiting(port); - this.#waitForSender.delete(id); - } else { - this.#pool.set(id, port); - } - }); - } - - receive(id: string): PortStreams { - const pooledPort = this.#pool.get(id); - if (pooledPort) { - this.#pool.delete(id); - return portToStreams(pooledPort); - } - return portFactoryToStreams(() => { - return new Promise((resolve) => { - this.#waitForSender.set(id, resolve); - }); - }); - } - - send(id: string): PortStreams { - const { port1, port2 } = new MessageChannel(); - this.#worker.postMessage({ type: DISPATCHER_SEND, id, port: port2 }, [ - port2, - ]); - return portToStreams(port1); - } -} - -export class WorkerClientTransport - implements ClientTransport -{ - #reader: ReadableStreamDefaultReader; - #writer: WritableStreamDefaultWriter; - - constructor(streams: PortStreams) { - this.#reader = streams.readable.getReader(); - this.#writer = streams.writable.getWriter(); - } - - createClientStream() { - return { - writableRequests: streamFromWriter(this.#writer), - readableResponses: streamFromReader(this.#reader), - }; - } -} - -export class WorkerServerTransport - implements ServerTransport -{ - #clientStreams: PortStreams; - - constructor(streams: PortStreams) { - this.#clientStreams = streams; - } - - createServerStream(): ServerBidirectionalStream { - return { - readableRequests: this.#clientStreams - .readable as PatchedReadableStream, - writableResponses: this.#clientStreams.writable, - }; - } -} diff --git a/packages/breadboard/src/run.ts b/packages/breadboard/src/run.ts deleted file mode 100644 index 9bc1a8d69d1..00000000000 --- a/packages/breadboard/src/run.ts +++ /dev/null @@ -1,134 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { RunState } from "./run/types.js"; -import { loadRunnerState, saveRunnerState } from "./serialization.js"; -import { timestamp } from "./timestamp.js"; -import type { - InputValues, - NodeDescriptor, - OutputValues, - TraversalResult, - BreadboardRunResult, - RunResultType, -} from "./types.js"; - -export class RunResult implements BreadboardRunResult { - #type: RunResultType; - #state: TraversalResult; - // TODO: Remove #state and rename this to #state - #runState: RunState | undefined; - // TODO: Remove this once RunState machinery works - #invocationId; - #path: number[]; - - constructor( - state: TraversalResult, - type: RunResultType, - runState: RunState | undefined, - invocationId: number, - path: number[] - ) { - this.#state = state; - this.#type = type; - this.#runState = runState; - this.#invocationId = invocationId; - this.#path = path; - } - - get invocationId(): number { - return this.#invocationId; - } - - get path(): number[] { - return this.#path; - } - - get type(): RunResultType { - return this.#type; - } - - get node(): NodeDescriptor { - return this.#state.descriptor; - } - - get inputArguments(): InputValues { - return this.#state.inputs; - } - - set inputs(inputs: InputValues) { - this.#state.outputs = { - ...inputs, - ...this.#state.partialOutputs, - }; - } - - get outputs(): OutputValues { - // Remove "schema" input for the "output" node, because it always be - // the schema for the output, rather than an actual value passed over the - // wire. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { schema, ...outputs } = this.#state.inputs; - return outputs; - } - - get state(): TraversalResult { - return this.#state; - } - - save() { - return saveRunnerState(this.#type, this.#state); - } - - get runState(): RunState | undefined { - return this.#runState; - } - - get timestamp(): number { - return timestamp(); - } - - isAtExitNode(): boolean { - return ( - this.#state.newOpportunities.length === 0 && - this.#state.opportunities.length === 0 - ); - } - - static load(stringifiedResult: string): RunResult { - const { state, type } = loadRunnerState(stringifiedResult); - return new RunResult(state, type, undefined, 0, []); - } -} - -export class InputStageResult extends RunResult { - constructor( - state: TraversalResult, - runState: RunState | undefined, - invocationId: number, - path: number[] - ) { - super(state, "input", runState, invocationId, path); - } - - get outputs(): OutputValues { - throw new Error('Outputs are not available in the "input" stage'); - } -} - -export class OutputStageResult extends RunResult { - constructor(state: TraversalResult, invocationId: number, path: number[]) { - super(state, "output", undefined, invocationId, path); - } - - get inputArguments(): InputValues { - throw new Error('Input arguments are not available in the "output" stage'); - } - - set inputs(inputs: InputValues) { - throw new Error('Setting inputs is not available in the "output" stage'); - } -} diff --git a/packages/breadboard/src/run/index.ts b/packages/breadboard/src/run/index.ts deleted file mode 100644 index a1ce4570de0..00000000000 --- a/packages/breadboard/src/run/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { InputValues } from "../types.js"; -import { RunStateManager } from "./manager.js"; -import type { ManagedRunState, ReanimationState } from "./types.js"; - -export const createRunStateManager = ( - resumeFrom: ReanimationState = {}, - inputs?: InputValues -): ManagedRunState => { - return new RunStateManager(resumeFrom, inputs); -}; diff --git a/packages/breadboard/src/run/lifecycle.ts b/packages/breadboard/src/run/lifecycle.ts deleted file mode 100644 index a3c14afce65..00000000000 --- a/packages/breadboard/src/run/lifecycle.ts +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { loadRunnerState, saveRunnerState } from "../serialization.js"; -import { MachineResult } from "../traversal/result.js"; -import type { - Edge, - NodeIdentifier, - OutputValues, - TraversalResult, -} from "../types.js"; -import { Registry } from "./registry.js"; -import type { - LifecyclePathRegistryEntry, - ManagedRunStateLifecycle, - ReanimationState, - ReanimationStateCache, - ReanimationStateVisits, - RunStackEntry, - RunState, -} from "./types.js"; -import { VisitTracker } from "./visit-tracker.js"; - -// TODO: Support stream serialization somehow. -// see https://github.com/breadboard-ai/breadboard/issues/423 - -function toReanimationState( - root: LifecyclePathRegistryEntry, - visits: VisitTracker -): ReanimationState { - function pathToString(path: number[]): string { - return path.join("-"); - } - - function descend( - entry: LifecyclePathRegistryEntry, - path: number[], - result: ReanimationStateCache - ) { - for (const [index, child] of entry.children.entries()) { - if (!child) continue; - const newPath = [...path, index]; - if (child.data) { - result[pathToString(path)] = child.data; - } - descend(child, newPath, result); - } - } - - const states: ReanimationStateCache = {}; - descend(root, [], states); - return { states, visits: visits.visited() }; -} - -export class LifecycleManager implements ManagedRunStateLifecycle { - #stack: RunState; - #registry: Registry; - #visits: VisitTracker; - - constructor(visits?: ReanimationStateVisits) { - this.#stack = []; - this.#registry = new Registry(); - this.#visits = new VisitTracker(visits); - } - - async supplyPartialOutputs( - outputs: OutputValues, - invocationPath: number[] - ): Promise { - const state = this.#registry.find(invocationPath)?.data; - if (!state) { - console.warn( - `No state found for path ${invocationPath}, partialOutputs will be dropped` - ); - return; - } - const unpackedState = loadRunnerState(state.state!).state; - unpackedState.partialOutputs = outputs; - state.state = saveRunnerState("nodestart", unpackedState); - } - - dispatchGraphStart(url: string, path: number[]): void { - const entry = this.#registry.create(path); - if (entry) { - entry.data = { ...entry.data, url, path }; - } - this.#stack.push({ url, path }); - } - - dispatchSkip(): void { - // Do nothing for now. - } - - dispatchEdge(_edge: Edge): void { - // Do nothing for now. - } - - async dispatchNodeStart( - result: TraversalResult, - invocationPath: number[] - ): Promise { - this.#visits.visit(result.descriptor.id, invocationPath); - if (this.#stack.length === 0) { - return; - } - const entry = this.#registry.create(invocationPath); - const state = saveRunnerState("nodestart", result); - const last = this.#stack[this.#stack.length - 1]; - if (last) { - last.state = state; - last.path = invocationPath; - } - entry.data = { url: undefined, state, path: invocationPath }; - } - - dispatchNodeEnd(outputs: OutputValues, invocationPath: number[]): void { - const entry = this.#registry.find(invocationPath); - if (entry?.data) { - entry.data.outputs = outputs; - } - } - - dispatchGraphEnd(): void { - // TODO: implement - } - - pathFor(node: NodeIdentifier): number[] | undefined { - return this.#visits.pathFor(node); - } - - state(): RunState { - return this.#stack; - } - - reanimationState(): ReanimationState { - return toReanimationState(this.#registry.root, this.#visits); - } -} - -export const traversalResultFromStack = ( - stack: RunState -): MachineResult | undefined => { - const { state } = stack[stack.length - 1]; - return state ? loadRunnerState(state).state : undefined; -}; diff --git a/packages/breadboard/src/run/manager.ts b/packages/breadboard/src/run/manager.ts deleted file mode 100644 index fa987083fae..00000000000 --- a/packages/breadboard/src/run/manager.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { InputValues } from "../types.js"; -import { LifecycleManager } from "./lifecycle.js"; -import { Reanimator } from "./reanimator.js"; -import type { - ManagedRunState, - ReanimationController, - ReanimationState, -} from "./types.js"; - -export class RunStateManager implements ManagedRunState { - #lifecycle: LifecycleManager; - #inputs?: InputValues; - #resumeFrom: ReanimationState; - - constructor(resumeFrom: ReanimationState, inputs?: InputValues) { - this.#resumeFrom = resumeFrom; - this.#lifecycle = new LifecycleManager(resumeFrom?.visits); - this.#inputs = inputs; - } - - lifecycle() { - // TODO: Lifecycle during reanimation should be doing - // nothing, since we're reconstructing the state of - // the run from a previously saved state. - return this.#lifecycle; - } - - reanimation(): ReanimationController { - return new Reanimator(this.#resumeFrom, this.#inputs); - } -} diff --git a/packages/breadboard/src/run/node-invoker.ts b/packages/breadboard/src/run/node-invoker.ts deleted file mode 100644 index 55035ee966f..00000000000 --- a/packages/breadboard/src/run/node-invoker.ts +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createOutputProvider, RequestedInputsManager } from "../bubble.js"; -import { resolveBoardCapabilitiesInInputs } from "../capability.js"; -import { callHandler, getHandler } from "../handler.js"; -import { SENTINEL_BASE_URL } from "../loader/loader.js"; -import { RunResult } from "../run.js"; -import type { - GraphDescriptor, - NodeHandlerContext, - OutputValues, - RunArguments, - TraversalResult, -} from "../types.js"; - -type ResultSupplier = (result: RunResult) => Promise; - -export class NodeInvoker { - #requestedInputs: RequestedInputsManager; - #resultSupplier: ResultSupplier; - #graph: GraphDescriptor; - #context: NodeHandlerContext; - - constructor( - args: RunArguments, - graph: GraphDescriptor, - next: (result: RunResult) => Promise - ) { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { inputs, ...context } = args; - this.#requestedInputs = new RequestedInputsManager(args); - this.#resultSupplier = next; - this.#graph = graph; - this.#context = context; - } - - async invokeNode(result: TraversalResult, invocationPath: number[]) { - const { inputs, descriptor } = result; - const { kits = [], base = SENTINEL_BASE_URL, state } = this.#context; - let outputs: OutputValues | undefined = undefined; - - const handler = await getHandler(descriptor.type, this.#context); - - const newContext: NodeHandlerContext = { - ...this.#context, - descriptor, - board: this.#graph, - // TODO: Remove this, since it is now the same as `board`. - outerGraph: this.#graph, - base, - kits, - requestInput: this.#requestedInputs.createHandler( - this.#resultSupplier, - result - ), - provideOutput: createOutputProvider( - this.#resultSupplier, - result, - this.#context - ), - invocationPath, - state, - }; - - outputs = (await callHandler( - handler, - resolveBoardCapabilitiesInInputs(inputs, this.#context, this.#graph.url), - newContext - )) as OutputValues; - - return outputs; - } -} diff --git a/packages/breadboard/src/run/reanimator.ts b/packages/breadboard/src/run/reanimator.ts deleted file mode 100644 index ba90f622b64..00000000000 --- a/packages/breadboard/src/run/reanimator.ts +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { loadRunnerState } from "../serialization.js"; -import { InputValues } from "../types.js"; -import { - ReanimationController, - ReanimationFrame, - ReanimationFrameController, - ReanimationMode, - ReanimationState, - ReplayResults, - ResumeResults, -} from "./types.js"; - -export class Reanimator implements ReanimationController { - #resumeFrom: ReanimationState; - #inputs?: InputValues; - - constructor(resumeFrom: ReanimationState, inputs?: InputValues) { - this.#resumeFrom = resumeFrom; - this.#inputs = inputs; - } - - enter(invocationPath: number[]): ReanimationFrameController { - const entryId = invocationPath.join("-"); - const cache = this.#resumeFrom.states; - const entry = cache?.[entryId]; - if (!entry) { - return new FrameReanimator(undefined); - } - if (!entry || !entry.state) { - throw new Error("Cannot reanimate without a state"); - } - const result = loadRunnerState(entry.state).state; - result.outputs = { - ...this.#inputs, - ...result.partialOutputs, - }; - this.#inputs = undefined; - const replayOutputs = entry.outputs ? [entry.outputs] : []; - - // Always return the new instance: - // wraps the actual ReanimationFrame, if any. - return new FrameReanimator({ - result, - invocationPath: entry.path, - replayOutputs, - }); - } -} - -export class FrameReanimator implements ReanimationFrameController { - #frame: ReanimationFrame | undefined; - - constructor(frame: ReanimationFrame | undefined) { - this.#frame = frame; - } - - mode(): ReanimationMode { - if (!this.#frame) { - return "none"; - } - if (this.#frame.replayOutputs.length > 0) { - return "replay"; - } - return "resume"; - } - - replay(): ReplayResults { - if (!this.#frame) { - throw new Error("Cannot replay without a frame"); - } - if (this.#frame.replayOutputs.length === 0) { - throw new Error("Cannot replay without replayOutputs"); - } - const result = this.#frame.result; - // Mutates replayOutputs. This is intentional. - result.inputs = this.#frame.replayOutputs.shift()!; - const path = this.#frame.invocationPath; - const invocationId = path[path.length - 1]; - - return { result, invocationId, path }; - } - - resume(): ResumeResults { - if (!this.#frame) { - throw new Error("Cannot resume without a frame"); - } - const invocationPath = this.#frame.invocationPath; - const result = this.#frame.result; - - return { invocationPath, result }; - } -} diff --git a/packages/breadboard/src/run/registry.ts b/packages/breadboard/src/run/registry.ts deleted file mode 100644 index 021c2279401..00000000000 --- a/packages/breadboard/src/run/registry.ts +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { LifecyclePathRegistryEntry } from "./types.js"; - -export const emptyEntry = () => ({ - children: [], - data: null, -}); - -// A more generic clone of inspector/run/PathRegistry -// TODO: Reconcile the two implementations. -export class Registry { - root: LifecyclePathRegistryEntry; - // parent: LifecyclePathRegistryEntry | null; - - constructor(root: LifecyclePathRegistryEntry = emptyEntry()) { - this.root = root; - } - - // constructor(parent: LifecyclePathRegistryEntry | null) { - // this.parent = parent; - // } - - /** - * The main traversal function for the path registry. It will find the - * entry for the given path, creating it if permitted, and return it. - * - * This function is what builds the graph tree. - * - * @param readonly -- If true, the registry is read-only and will not be - * modified. - * @param registry -- The registry to traverse. Used in recursion. - * @param fullPath -- The full path to the current node. Passed along during - * recursion. - * @param path -- The current path to the node. Used in recursion. - * @returns -- The entry for the given path, or undefined if the path is - * empty or invalid. - */ - #findOrCreate( - current: LifecyclePathRegistryEntry, - readonly: boolean, - fullPath: number[], - path: number[] - ): LifecyclePathRegistryEntry | null { - // Marking events dirty, because we're about to mutate something within - // this swath of the registry. - const [head, ...tail] = path; - if (head === undefined) { - return null; - } - let entry = current.children[head]; - if (!entry) { - if (tail.length !== 0) { - // If you see this message in the console, it's a problem with the - // underlying runner. The runner should always provide paths - // incrementally, so there should never be a situation where we don't - // have a registry entry for an index in the middle of the path. - console.warn("Path registry entry not found for", path, "in", fullPath); - } - if (readonly) { - console.warn("Path registry is read-only. Not adding", fullPath); - return null; - } - entry = current.children[head] = emptyEntry(); - } - if (tail.length === 0) { - return entry; - } - return this.#findOrCreate(entry, readonly, fullPath, tail); - } - - find(path: number[]) { - return this.#findOrCreate(this.root, true, path, path); - } - - create(path: number[]) { - return this.#findOrCreate( - this.root, - false, - path, - path - ) as LifecyclePathRegistryEntry; - } -} diff --git a/packages/breadboard/src/run/run-graph.ts b/packages/breadboard/src/run/run-graph.ts deleted file mode 100644 index 995e81788eb..00000000000 --- a/packages/breadboard/src/run/run-graph.ts +++ /dev/null @@ -1,203 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - GraphDescriptor, - OutputValues, -} from "@google-labs/breadboard-schema/graph.js"; -import { bubbleUpInputsIfNeeded, bubbleUpOutputsIfNeeded } from "../bubble.js"; -import { resolveBoardCapabilities } from "../capability.js"; -import { InputStageResult, OutputStageResult } from "../run.js"; -import { timestamp } from "../timestamp.js"; -import { TraversalMachine } from "../traversal/machine.js"; -import type { - BreadboardRunResult, - RunArguments, - TraversalResult, -} from "../types.js"; -import { asyncGen } from "../utils/async-gen.js"; -import { NodeInvoker } from "./node-invoker.js"; - -/** - * Runs a graph in "run" mode. See - * https://breadboard-ai.github.io/breadboard/docs/reference/runtime-semantics/#run-mode - * for more details. - */ -export async function* runGraph( - graph: GraphDescriptor, - args: RunArguments = {}, - resumeFrom?: TraversalResult -): AsyncGenerator { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { inputs, start, ...context } = args; - const { probe, state, invocationPath = [] } = context; - - const lifecycle = state?.lifecycle(); - yield* asyncGen(async (next) => { - const nodeInvoker = new NodeInvoker(args, graph, next); - - lifecycle?.dispatchGraphStart(graph.url!, invocationPath); - - let invocationId = 0; - - const reanimation = state?.reanimation(); - if (reanimation) { - const frame = reanimation.enter(invocationPath); - const mode = frame.mode(); - switch (mode) { - case "replay": { - // This can only happen when `runGraph` is called by `invokeGraph`, - // which means that all we need to do is provide the output and - // return. - const { result, invocationId: id, path } = frame.replay(); - await next(new OutputStageResult(result, id, path)); - // The nodeend and graphend will be dispatched by `invokeGraph`. - return; - } - case "resume": { - const { result, invocationPath } = frame.resume(); - - resumeFrom = result; - // Adjust invocationId to match the point from which we are resuming. - invocationId = invocationPath[invocationPath.length - 1]; - - await lifecycle?.dispatchNodeStart(result, invocationPath); - - let outputs: OutputValues | undefined = undefined; - - const type = result.descriptor.type; - if (!(type === "input" || type === "output")) { - outputs = await nodeInvoker.invokeNode(result, invocationPath); - result.outputs = outputs; - resumeFrom = result; - } else { - outputs = result.outputs; - } - - lifecycle?.dispatchNodeEnd(outputs, invocationPath); - - await probe?.report?.({ - type: "nodeend", - data: { - node: result.descriptor, - inputs: result.inputs, - outputs: outputs as OutputValues, - path: invocationPath, - timestamp: timestamp(), - }, - }); - } - } - } - - const path = () => [...invocationPath, invocationId]; - - const machine = new TraversalMachine(graph, resumeFrom, start); - if (!resumeFrom) { - await probe?.report?.({ - type: "graphstart", - data: { graph, path: invocationPath, timestamp: timestamp() }, - }); - } - - for await (const result of machine) { - context?.signal?.throwIfAborted(); - - invocationId++; - const { inputs, descriptor, missingInputs } = result; - - lifecycle?.dispatchEdge(result.current); - await probe?.report?.({ - type: "edge", - data: { - edge: result.current, - to: path(), - from: lifecycle?.pathFor(result.current.from), - timestamp: timestamp(), - value: inputs, - }, - }); - - if (result.skip) { - lifecycle?.dispatchSkip(); - await probe?.report?.({ - type: "skip", - data: { - node: descriptor, - inputs, - missingInputs, - path: path(), - timestamp: timestamp(), - }, - }); - continue; - } - - await lifecycle?.dispatchNodeStart(result, path()); - - await probe?.report?.({ - type: "nodestart", - data: { - node: descriptor, - inputs, - path: path(), - timestamp: timestamp(), - }, - state: lifecycle?.state(), - }); - - let outputs: OutputValues | undefined = undefined; - - if (descriptor.type === "input") { - await next( - new InputStageResult(result, lifecycle?.state(), invocationId, path()) - ); - await bubbleUpInputsIfNeeded( - graph, - context, - descriptor, - result, - path(), - lifecycle?.state() - ); - outputs = result.outputs - ? await resolveBoardCapabilities(result.outputs, context, graph.url) - : undefined; - } else if (descriptor.type === "output") { - if ( - !(await bubbleUpOutputsIfNeeded(inputs, descriptor, context, path())) - ) { - await next(new OutputStageResult(result, invocationId, path())); - } - outputs = result.outputs; - } else { - outputs = await nodeInvoker.invokeNode(result, path()); - } - - lifecycle?.dispatchNodeEnd(outputs, path()); - - await probe?.report?.({ - type: "nodeend", - data: { - node: descriptor, - inputs, - outputs: outputs as OutputValues, - path: path(), - timestamp: timestamp(), - }, - }); - - result.outputs = outputs; - } - - lifecycle?.dispatchGraphEnd(); - - await probe?.report?.({ - type: "graphend", - data: { path: invocationPath, timestamp: timestamp() }, - }); - }); -} diff --git a/packages/breadboard/src/run/types.ts b/packages/breadboard/src/run/types.ts deleted file mode 100644 index 18344bf3552..00000000000 --- a/packages/breadboard/src/run/types.ts +++ /dev/null @@ -1,159 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - Edge, - NodeIdentifier, - OutputValues, - TraversalResult, -} from "../types.js"; - -/** - * Sequential number of the invocation of a node. - * Useful for understanding the relative position of a - * given invocation of node within the run. - */ -export type InvocationId = number; - -/** - * Information about a given invocation of a graph and - * node within the graph. - */ -export type RunStackEntry = { - /** - * The URL of the graph being run; - */ - url: string | undefined; - /** - * The invocation path of the node within the graph. - */ - path: number[]; - /** - * The state of the graph traversal at the time of the invocation. - */ - state?: string; - /** - * Outputs of the node if it has been run. - */ - outputs?: OutputValues; -}; - -/** - * A stack of all invocations of graphs and nodes within the graphs. - * The stack is ordered from the outermost graph to the innermost graph - * that is currently being run. - * Can be used to understand the current state of the run. - */ -export type RunState = RunStackEntry[]; - -export type LifecyclePathRegistryEntry = { - children: LifecyclePathRegistryEntry[]; - // parent: LifecyclePathRegistryEntry | null; - data: Data | null; -}; - -export type ManagedRunStateLifecycle = { - /** - * Signifies the beginning of a new graph being run or invoked. - * @param url -- url of the graph that is starting - */ - dispatchGraphStart(url: string, invocationPath: number[]): void; - dispatchNodeStart( - result: TraversalResult, - invocationPath: number[] - ): Promise; - dispatchNodeEnd( - outputs: OutputValues | undefined, - invocationPath: number[] - ): void; - dispatchGraphEnd(): void; - dispatchSkip(): void; - dispatchEdge(edge: Edge): void; - supplyPartialOutputs( - outputs: OutputValues, - invocationPath: number[] - ): Promise; - state(): RunState; - reanimationState(): ReanimationState; - pathFor(node: NodeIdentifier): number[] | undefined; -}; - -/** - * The representation of Breadboard runtime. - * TODO: Rename to ManagedRuntime. - */ -export type ManagedRunState = { - /** - * The entry point for signaling run lifecycle changes. - */ - lifecycle(): ManagedRunStateLifecycle; - reanimation(): ReanimationController; -}; - -export type ReanimationStateCache = Record; -export type ReanimationStateVisits = [NodeIdentifier, number[]][]; - -export type ReanimationState = { - states?: ReanimationStateCache; - visits?: ReanimationStateVisits; -}; - -export type ReanimationMode = - /** - * This run is just replaying existing results. - */ - | "replay" - /** - * This run is resuming from a previously saved state. - */ - | "resume" - /** - * This run is running normally. - */ - | "none"; - -export type ReanimationController = { - enter(invocationPath: number[]): ReanimationFrameController; -}; - -export type ReanimationFrameController = { - mode(): ReanimationMode; - replay(): ReplayResults; - resume(): ResumeResults; -}; - -export type ReplayResults = { - result: TraversalResult; - invocationId: InvocationId; - path: number[]; -}; - -export type ResumeResults = { - result: TraversalResult; - invocationPath: number[]; -}; - -export type ReanimationFrame = { - /** - * The state to resume from. - */ - result: TraversalResult; - /** - * Invocation path of the node. - */ - invocationPath: number[]; - /** - * The results of all completed `invokeGraph` calls. - * This list will be empty for the typical invoke case, - * but will contain values for nodes that call `invokeGraph` - * more than once during their execution (like `map` - * and `reduce`) - * - * The order is the same as the order of the `invokeGraph` - * calls from the node. - */ - replayOutputs: OutputValues[]; -}; diff --git a/packages/breadboard/src/run/visit-tracker.ts b/packages/breadboard/src/run/visit-tracker.ts deleted file mode 100644 index 17053bb90d5..00000000000 --- a/packages/breadboard/src/run/visit-tracker.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { NodeIdentifier } from "../types.js"; -import { ReanimationStateVisits } from "./types.js"; - -/** - * Tracks paths of visited nodes. Uses the "last visited node" approach. - * This might not be perfectly accurate, since we don't actually know if - * the last visited node is the one where the edge comes from. - * However, it should work well enough in most cases. - */ -export class VisitTracker { - #visited = new Map(); - - constructor(visits: ReanimationStateVisits = []) { - this.#visited = new Map(visits); - } - - visit(node: string, path: number[]) { - this.#visited.set(node, path); - } - - pathFor(node: string): number[] | undefined { - return this.#visited.get(node); - } - - visited(): [NodeIdentifier, number[]][] { - return Array.from(this.#visited.entries()); - } -} diff --git a/packages/breadboard/src/schema.ts b/packages/breadboard/src/schema.ts deleted file mode 100644 index 36b2b35932e..00000000000 --- a/packages/breadboard/src/schema.ts +++ /dev/null @@ -1,206 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { InputValues, Schema } from "./types.js"; - -export type SchemaProperties = Record; - -export type SchemaType = - | "null" - | "boolean" - | "object" - | "array" - | "number" - | "integer" - | "string"; - -export const getSchemaType = (value: unknown): SchemaType => { - if (value === null || value === undefined) { - return "null"; - } - if (Array.isArray(value)) { - return "array"; - } - return typeof value as SchemaType; -}; - -export class SchemaBuilder { - type = "object"; - additionalProperties = false; - required: string[] = []; - properties: SchemaProperties = {}; - - build(): Schema { - const result: Schema = { - type: "object", - properties: this.properties, - }; - if (!this.additionalProperties) { - result.additionalProperties = false; - } - if (this.required.length > 0) { - result.required = this.required; - } - return result; - } - - addSchema(schema: Schema) { - if (schema.type === "object") { - this.addProperties(schema.properties); - this.addRequired(schema.required); - this.setAdditionalProperties(schema.additionalProperties as boolean); - } - return this; - } - - setAdditionalProperties(additionalProperties?: Schema | boolean) { - if (additionalProperties !== undefined) { - this.additionalProperties = !!additionalProperties; - } - return this; - } - - addInputs(inputs?: InputValues) { - if (!inputs) return this; - Object.entries(inputs).forEach(([name, value]) => { - this.addProperty(name, { type: getSchemaType(value) }); - }); - return this; - } - - addProperty(name: string, schema: Schema) { - this.properties[name] = schema; - return this; - } - - addProperties(properties?: SchemaProperties) { - if (!properties) return this; - Object.entries(properties).forEach(([name, schema]) => { - this.addProperty(name, schema); - }); - return this; - } - - addRequired(required?: string[] | string) { - if (!required) return this; - - if (typeof required === "string") { - this.required = [...new Set([...this.required, required])]; - } else if (Array.isArray(required) && required.length > 0) { - this.required = [...new Set([...this.required, ...required])]; - } - this.required.sort(); - return this; - } - - static empty(additionalProperties = false): Schema { - return new SchemaBuilder() - .setAdditionalProperties(additionalProperties) - .build(); - } -} - -/** - * Provides a way to manually handle schema merging. - * Currently only invoked to handle the `additionalProperties` property. - */ -export type ReducerFunction = (result: Schema, schema: Schema) => void; - -/** - * Combines multiple schemas into a single schema. This is lossy, since - * the same-named properties will be overridden (last one wins). However, - * it's good enough to communicate the overall shape of the combined schema. - * @param schemas - the schemas to combine - * @returns - the combined schema - */ -export const combineSchemas = ( - schemas: Schema[], - reducer?: ReducerFunction -): Schema => { - const result: Schema = {}; - schemas.forEach((schema) => { - if (schema.type === "object") { - if (schema.properties) { - result.properties = { ...result.properties, ...schema.properties }; - } - if (schema.required) { - result.required = [ - ...(result.required ?? []), - ...(schema.required ?? []), - ]; - } - if (reducer) { - reducer(result, schema); - } else { - if (schema.additionalProperties !== undefined) { - result.additionalProperties = schema.additionalProperties; - } - } - } - if (schema.behavior) { - result.behavior ??= []; - result.behavior.push(...schema.behavior); - } - }); - result.type = "object"; - if (result.required) { - result.required = [...new Set(result.required)]; - result.required?.sort(); - } - return result; -}; - -/** - * Removes a property from a schema (assumes it to be type = object). - * - * @param schema -- Schema to remove the property from - * @param property -- the property to remove - * @returns -- a new Schema instance with removed property. - */ -export const removeProperty = (schema: Schema, property: string): Schema => { - const entries = Object.entries(schema.properties || {}); - if (entries.length == 0) { - return schema; - } - const index = entries.findIndex(([name]) => { - return name === property; - }); - if (index == -1) { - return schema; - } - entries.splice(index, 1); - return { - ...schema, - properties: Object.fromEntries(entries), - }; -}; - -export const filterBySchema = >( - values: T, - schema?: Schema -): T => { - const names = Object.keys(schema?.properties || {}); - return Object.fromEntries( - Object.entries(values).filter(([name]) => names.includes(name)) - ) as T; -}; - -export const filterProperties = ( - schema: Schema, - filterFunction: (property: Schema) => boolean -): Schema => { - const entries = Object.entries(schema.properties || {}); - if (entries.length == 0) { - return schema; - } - const result = structuredClone(schema); - result.properties = Object.fromEntries( - entries.filter(([, schema]) => { - return filterFunction(schema); - }) - ); - return result; -}; diff --git a/packages/breadboard/src/serialization.ts b/packages/breadboard/src/serialization.ts deleted file mode 100644 index 511e44dadc5..00000000000 --- a/packages/breadboard/src/serialization.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { MachineResult } from "./traversal/result.js"; -import { TraversalResult } from "./types.js"; - -export const replacer = (key: string, value: unknown) => { - if (!(value instanceof Map)) return value; - return { $type: "Map", value: Array.from(value.entries()) }; -}; - -export const reviver = ( - key: string, - value: unknown & { - $type?: string; - value: Iterable; - } -) => { - const { $type } = (value || {}) as { $type?: string }; - return $type == "Map" && value.value - ? new Map(value.value) - : value; -}; - -export const saveRunnerState = (type: string, result: TraversalResult) => { - const state = result; - return JSON.stringify({ state, type }, replacer); -}; - -export const loadRunnerState = (s: string) => { - const { state: o, type } = JSON.parse(s, reviver); - const state = MachineResult.fromObject(o); - return { state, type }; -}; diff --git a/packages/breadboard/src/stream.ts b/packages/breadboard/src/stream.ts deleted file mode 100644 index 846a6d813e7..00000000000 --- a/packages/breadboard/src/stream.ts +++ /dev/null @@ -1,356 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { Capability, NodeValue } from "./types.js"; - -const STREAM_KIND = "stream" as const; - -export interface StreamCapabilityType extends Capability { - kind: typeof STREAM_KIND; - stream: ReadableStream; -} - -export class StreamCapability - implements StreamCapabilityType -{ - kind = STREAM_KIND; - stream: ReadableStream; - - constructor(stream: ReadableStream) { - this.stream = stream; - } -} - -export const clone = (streamCapability: StreamCapabilityType) => { - const [leave, take] = streamCapability.stream.tee(); - streamCapability.stream = leave; - return take; -}; - -export const isStreamCapability = (object: unknown) => { - const maybeStream = object as StreamCapabilityType; - return ( - maybeStream && - maybeStream.kind && - maybeStream.kind === STREAM_KIND && - maybeStream.stream instanceof ReadableStream - ); -}; - -// TODO: Remove this once MessageController is gone. -const findStreams = (value: NodeValue, foundStreams: ReadableStream[]) => { - if (Array.isArray(value)) { - value.forEach((item: NodeValue) => { - findStreams(item, foundStreams); - }); - } else if (typeof value === "object") { - if (value === null || value === undefined) return; - const maybeCapability = value as StreamCapabilityType; - if (maybeCapability.kind && maybeCapability.kind === STREAM_KIND) { - foundStreams.push(maybeCapability.stream); - } else { - Object.values(value as object).forEach((item) => { - findStreams(item, foundStreams); - }); - } - } -}; - -export const stringifyWithStreams = (value: unknown) => { - const foundStreams: ReadableStream[] = []; - return { - value: JSON.stringify(value, (key, value) => { - if (isStreamCapability(value)) { - foundStreams.push(value.stream); - return { $type: "Stream", id: foundStreams.length - 1 }; - } - return value; - }), - streams: foundStreams, - }; -}; - -export const parseWithStreams = ( - value: string, - getStream: (id: number) => ReadableStream -) => { - const parsed = JSON.parse(value, (key, value) => { - if (typeof value === "object" && value !== null) { - if (value.$type === "Stream" && typeof value.id === "number") { - return new StreamCapability(getStream(value.id)); - } - } - return value; - }); - return parsed; -}; - -export const getStreams = (value: NodeValue) => { - const foundStreams: ReadableStream[] = []; - findStreams(value, foundStreams); - return foundStreams; -}; - -/** - * Stubs out all streams in the input values with empty streams. - * This is useful when we don't want the streams to be transferred. - * @param data - * @returns - */ -export const stubOutStreams = (data: unknown): unknown => { - const stringified = stringifyWithStreams(data).value; - return parseWithStreams(stringified, () => new ReadableStream()); -}; - -export type PatchedReadableStream = ReadableStream & AsyncIterable; - -interface MessagePortLike { - postMessage(message: unknown, transfer: Transferable[]): void; - onmessage: ((ev: MessageEvent) => unknown) | null; -} - -export type PortStreams = { - readable: ReadableStream; - writable: WritableStream; -}; - -export const portToStreams = ( - port: MessagePortLike -): PortStreams => { - const readable = new ReadableStream({ - start(controller) { - port.onmessage = (ev) => { - if (ev.data === null) { - controller.close(); - return; - } - controller.enqueue(ev.data); - }; - }, - cancel() { - port.onmessage = null; - }, - }); - const writable = new WritableStream({ - write(chunk) { - const stringified = stringifyWithStreams(chunk); - port.postMessage(chunk, stringified.streams); - }, - close() { - port.postMessage(null, []); - }, - }); - return { - readable, - writable, - }; -}; - -export const portFactoryToStreams = ( - portFactory: () => Promise -): PortStreams => { - let streams: PortStreams; - const streamsAvailable = new Promise((resolve) => { - portFactory().then((port) => { - streams = portToStreams(port); - resolve(); - }); - }); - const readable = new ReadableStream({ - async start() { - await streamsAvailable; - }, - pull(controller) { - return streams.readable.pipeTo( - new WritableStream({ - write(chunk) { - controller.enqueue(chunk); - }, - }) - ); - }, - cancel() { - streams.readable.cancel(); - }, - }); - const writable = new WritableStream({ - async start() { - await streamsAvailable; - }, - async write(chunk) { - const writer = streams.writable.getWriter(); - await writer.write(chunk); - writer.releaseLock(); - }, - async close() { - await streams.writable.close(); - }, - async abort(reason) { - await streams.writable.abort(reason); - }, - }); - return { - readable, - writable, - }; -}; - -export class WritableResult { - #writer: WritableStreamDefaultWriter; - data: Read; - - constructor(value: Read, writer: WritableStreamDefaultWriter) { - this.#writer = writer; - this.data = value; - } - - async reply(chunk: Write) { - await this.#writer.write(chunk); - } -} - -class StreamsAsyncIterator - implements AsyncIterator, void, unknown> -{ - #reader: ReadableStreamDefaultReader; - #writer: WritableStreamDefaultWriter; - constructor(writable: WritableStream, readable: ReadableStream) { - this.#reader = readable.getReader(); - this.#writer = writable.getWriter(); - } - - async next(): Promise, void>> { - const { done, value } = await this.#reader.read(); - if (done) { - this.#writer.close(); - return { done, value: undefined }; - } - return { - done: false, - value: new WritableResult(value, this.#writer), - }; - } - - async return(): Promise, void>> { - this.#writer.close(); - return { done: true, value: undefined }; - } - - async throw( - err: Error - ): Promise, void>> { - this.#writer.abort(err); - return { done: true, value: undefined }; - } -} - -export type AsyncIterableWithStart = AsyncIterable & { - start: (chunk: S) => Promise; -}; - -/** - * A helper to convert a pair of streams to an async iterable that follows - * the following protocol: - * - The async iterable yields a `WritableResult` object. - * - The `WritableResult` object contains the data from the readable stream. - * - The `WritableResult` object has a `reply` method that can be used to - * write a value as a reply to to data in the readable stream. - * - * This is particularly useful with bi-directional streams, when the two - * streams are semantically connected to each other. - * - * @param writable The writable stream. - * @param readable The readable stream. - * @returns An async iterable. - */ -export const streamsToAsyncIterable = ( - writable: WritableStream, - readable: ReadableStream -): AsyncIterableWithStart, Write> => { - return { - async start(chunk: Write) { - const writer = writable.getWriter(); - await writer.write(chunk); - writer.releaseLock(); - }, - [Symbol.asyncIterator]() { - return new StreamsAsyncIterator(writable, readable); - }, - }; -}; - -// Polyfill to make ReadableStream async iterable -// See https://bugs.chromium.org/p/chromium/issues/detail?id=929585 -export const patchReadableStream = () => { - // eslint-disable-next-line - // @ts-ignore - ReadableStream.prototype[Symbol.asyncIterator] || - // eslint-disable-next-line - // @ts-ignore - (ReadableStream.prototype[Symbol.asyncIterator] = async function* () { - const reader = this.getReader(); - try { - while (true) { - const { done, value } = await reader.read(); - if (done) return; - yield value; - } - } finally { - reader.releaseLock(); - } - }); -}; - -// A polyfill for ReadableStream.from: -// See https://streams.spec.whatwg.org/#rs-from -// TODO: Do a proper TypeScript types polyfill. -export const streamFromAsyncGen = ( - iterator: AsyncIterableIterator -): PatchedReadableStream => { - return new ReadableStream({ - async pull(controller) { - const { value, done } = await iterator.next(); - - if (done) { - controller.close(); - return; - } - controller.enqueue(value); - }, - }) as PatchedReadableStream; -}; - -export const streamFromReader = ( - reader: ReadableStreamDefaultReader -) => { - return new ReadableStream( - { - async pull(controller) { - const { value, done } = await reader.read(); - - if (done) { - controller.close(); - return; - } - controller.enqueue(value); - }, - }, - { highWaterMark: 0 } - ) as PatchedReadableStream; -}; - -export const streamFromWriter = ( - writer: WritableStreamDefaultWriter -) => { - return new WritableStream( - { - async write(chunk) { - return writer.write(chunk); - }, - }, - { highWaterMark: 0 } - ); -}; diff --git a/packages/breadboard/src/traversal/index.ts b/packages/breadboard/src/traversal/index.ts deleted file mode 100644 index d32eb101cdd..00000000000 --- a/packages/breadboard/src/traversal/index.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { StartLabel, StartTag } from "@google-labs/breadboard-schema/graph.js"; -import { Edge, InputValues, NodeDescriptor } from "../types.js"; - -const requiredInputsFromEdges = (edges: Edge[]): string[] => { - return [ - ...new Set( - edges - .filter((edge: Edge) => !!edge.in && !edge.optional) - .map((edge: Edge) => edge.in || "") - ), - ]; -}; - -const isStartNode = ( - node: NodeDescriptor, - start: StartLabel = "default" -): boolean => { - if (!node.metadata?.tags) return false; - return node.metadata.tags.some((tag) => { - const startTag = tag as StartTag; - if (typeof startTag === "string") return startTag === "start"; - if (startTag.type !== "start") return false; - const label = startTag.label ?? "default"; - return start === label; - }); -}; - -/** - * This class holds important parts of the graph traversal algorithm. - */ -export class Traversal { - /** - * Computes the missing inputs for a node. A missing input is an input that is - * required by the node, but is not (yet) available in the current state. - * @param heads All the edges that point to the node. - * @param inputs The input values that will be passed to the node - * @param current The node that is being visited. - * @returns Array of missing input names. - */ - static computeMissingInputs( - heads: Edge[], - inputs: InputValues, - current: NodeDescriptor, - start?: StartLabel - ): string[] { - const requiredInputs: string[] = isStartNode(current, start) - ? [] - : requiredInputsFromEdges(heads); - const inputsWithConfiguration = new Set(); - Object.keys(inputs).forEach((key) => inputsWithConfiguration.add(key)); - if (current.configuration) { - Object.keys(current.configuration).forEach((key) => - inputsWithConfiguration.add(key) - ); - } - return requiredInputs.filter( - (input) => !inputsWithConfiguration.has(input) - ); - } -} diff --git a/packages/breadboard/src/traversal/machine.ts b/packages/breadboard/src/traversal/machine.ts deleted file mode 100644 index 4a44630362b..00000000000 --- a/packages/breadboard/src/traversal/machine.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { StartLabel } from "@google-labs/breadboard-schema/graph.js"; -import type { GraphDescriptor, TraversalResult } from "../types.js"; -import { TraversalMachineIterator } from "./iterator.js"; -import { GraphRepresentation } from "./representation.js"; -import { MachineResult } from "./result.js"; -import { MachineEdgeState } from "./state.js"; - -export class TraversalMachine implements AsyncIterable { - graph: GraphRepresentation; - previousResult?: TraversalResult; - - constructor( - descriptor: GraphDescriptor, - result?: TraversalResult, - start?: StartLabel - ) { - this.graph = new GraphRepresentation(descriptor, start); - this.previousResult = result; - } - - [Symbol.asyncIterator](): AsyncIterator { - return this.start(); - } - - start(): TraversalMachineIterator { - if (this.previousResult) - return new TraversalMachineIterator(this.graph, this.previousResult); - - const { entries } = this.graph; - if (entries.length === 0) throw new Error("No entry node found in graph."); - // Create fake edges to represent entry points. - const opportunities = entries.map((entry) => ({ - from: "$entry", - to: entry, - })); - const entryResult = new MachineResult( - { id: "$empty", type: "$empty" }, - {}, - [], - { from: "$entry", to: entries[0] }, - opportunities, - [], - new MachineEdgeState() - ); - return new TraversalMachineIterator(this.graph, entryResult); - } -} diff --git a/packages/breadboard/src/traversal/representation.ts b/packages/breadboard/src/traversal/representation.ts deleted file mode 100644 index 0b398895256..00000000000 --- a/packages/breadboard/src/traversal/representation.ts +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { StartLabel, StartTag } from "@google-labs/breadboard-schema/graph.js"; -import type { - Edge, - GraphDescriptor, - NodeDescriptor, - NodeIdentifier, -} from "../types.js"; - -export class GraphRepresentation { - start?: StartLabel; - /** - * Tails: a map of all outgoing edges, keyed by node id. - */ - tails: Map = new Map(); - - /** - * Heads: a map of all incoming edges, keyed by node id. - */ - heads: Map = new Map(); - - /** - * Nodes: a map of all nodes, keyed by node id. - */ - nodes: Map = new Map(); - - /** - * Entries: a list of all nodes that have no incoming edges. - */ - entries: NodeIdentifier[] = []; - - #notInHeads(id: NodeIdentifier) { - return !this.heads.has(id) || this.heads.get(id)?.length === 0; - } - - #findEntries() { - const entries = new Set(); - const start = this.start ?? "default"; - let hasStartLabels = false; - this.nodes.forEach((node) => { - node.metadata?.tags?.forEach((tag) => { - let startTag = tag as StartTag; - if (typeof startTag === "string" && startTag === "start") { - startTag = { type: "start", label: "default" }; - } - if (startTag.type === "start") { - const label = startTag.label ?? "default"; - hasStartLabels = true; - if (label === start) { - entries.add(node.id); - } - } - }); - }); - - // If there are tagged entries, return them. - if (entries.size > 0) { - return Array.from(entries); - } - - // If there were start labels present, return an empty array, since we - // are asked to traverse a graph from a non-existent entry point. - if (hasStartLabels) { - return []; - } - - // Otherwise, fall back to computing entries based on edges. - return Array.from(this.nodes.keys()).filter((node) => - this.#notInHeads(node) - ); - } - - constructor(descriptor: GraphDescriptor, start?: StartLabel) { - if (start) { - this.start = start; - } - this.tails = descriptor.edges.reduce((acc, edge) => { - const from = edge.from; - acc.has(from) ? acc.get(from)?.push(edge) : acc.set(from, [edge]); - return acc; - }, new Map()); - - this.heads = descriptor.edges.reduce((acc, edge) => { - const to = edge.to; - acc.has(to) ? acc.get(to)?.push(edge) : acc.set(to, [edge]); - return acc; - }, new Map()); - - this.nodes = descriptor.nodes.reduce((acc, node) => { - acc.set(node.id, node); - return acc; - }, new Map()); - - this.entries = this.#findEntries(); - } -} diff --git a/packages/breadboard/src/traversal/result.ts b/packages/breadboard/src/traversal/result.ts deleted file mode 100644 index 00fbc2b01e5..00000000000 --- a/packages/breadboard/src/traversal/result.ts +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - Edge, - QueuedNodeValuesState, - InputValues, - NodeDescriptor, - OutputValues, - TraversalResult, -} from "../types.js"; -import { MachineEdgeState } from "./state.js"; - -export class MachineResult implements TraversalResult { - descriptor: NodeDescriptor; - inputs: InputValues; - missingInputs: string[]; - current: Edge; - opportunities: Edge[]; - newOpportunities: Edge[]; - state: QueuedNodeValuesState; - outputs?: OutputValues; - partialOutputs?: OutputValues; - - constructor( - descriptor: NodeDescriptor, - inputs: InputValues, - missingInputs: string[], - currentOpportunity: Edge, - opportunities: Edge[], - newOpportunities: Edge[], - state: QueuedNodeValuesState, - partialOutputs?: OutputValues - ) { - this.descriptor = descriptor; - this.inputs = inputs; - this.missingInputs = missingInputs; - this.current = currentOpportunity; - this.opportunities = opportunities; - this.newOpportunities = newOpportunities; - this.state = state; - this.partialOutputs = partialOutputs; - } - - /** - * `true` if the machine decided that the node should be skipped, rather than - * visited. - */ - get skip(): boolean { - return this.missingInputs.length > 0; - } - - static fromObject(o: TraversalResult): MachineResult { - const edgeState = new MachineEdgeState(); - edgeState.constants = o.state.constants; - edgeState.state = o.state.state; - return new MachineResult( - o.descriptor, - o.inputs, - o.missingInputs, - o.current, - o.opportunities, - o.newOpportunities, - edgeState, - o.partialOutputs - ); - } -} diff --git a/packages/breadboard/src/traversal/state.ts b/packages/breadboard/src/traversal/state.ts deleted file mode 100644 index 3df06309c29..00000000000 --- a/packages/breadboard/src/traversal/state.ts +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - Edge, - QueuedNodeValuesState, - NodeIdentifier, - InputValues, - OutputValues, - NodeValue, - NodeValuesQueuesMap, -} from "../types.js"; - -export class MachineEdgeState implements QueuedNodeValuesState { - state: NodeValuesQueuesMap = new Map(); - constants: NodeValuesQueuesMap = new Map(); - - #queueOutput( - map: NodeValuesQueuesMap, - node: NodeIdentifier, - key: string, - value: NodeValue - ) { - let queuesMap = map.get(node); - if (!queuesMap) { - queuesMap = new Map(); - map.set(node, queuesMap); - } - let queue = queuesMap.get(key); - if (!queue) { - queue = []; - queuesMap.set(key, queue); - } - queue.push(value); - } - - /** - * Processes outputs by wiring them to the destinations according - * to the supplied edges. Assumes that the outputs were generated by - * the from node. - * - * @param opportunites {Edge[]} Edges to process - * @param outputs {OutputValues} Outputs to wire - */ - wireOutputs(opportunites: Edge[], outputs: OutputValues): void { - // Verify that all edges are from the same node. - if ( - opportunites.filter( - (opportunity) => opportunity.from != opportunites[0].from - ).length !== 0 - ) - throw new Error("All opportunities must be from the same node"); - - opportunites.forEach((opportunity) => { - const to = opportunity.to; - const out = opportunity.out; - const queuesMap = opportunity.constant ? this.constants : this.state; - if (!out) return; - if (out === "*") { - for (const key in outputs) { - const output = outputs[key]; - if (output != null && output != undefined) - this.#queueOutput(queuesMap, to, key, output); - } - } else if (opportunity.in) { - const output = outputs[out]; - // TODO: Check and document why we don't allow that - if (output != null && output != undefined) - this.#queueOutput(queuesMap, to, opportunity.in, output); - } - }); - } - - /** - * Returns the available inputs for a given node. - * - * @param nodeId {NodeIdentifier} The node to get the inputs for. - * @returns {InputValues} The available inputs. - */ - getAvailableInputs(nodeId: NodeIdentifier): InputValues { - const result: InputValues = {}; - - for (const queuesMap of [ - this.constants.get(nodeId), // Constants are overwritten by state. - this.state.get(nodeId), - ]) { - if (!queuesMap) continue; - for (const [key, queue] of queuesMap.entries()) { - if (queue.length === 0) continue; - result[key] = queue[0]; - } - } - return result; - } - - /** - * Shifts inputs from the queues. Leaves constants as is. - * - * @param nodeId {NodeIdentifier} The node to shift the inputs for. - * @param inputs {InputValues} The inputs that are used. - */ - useInputs(nodeId: NodeIdentifier, inputs: InputValues): void { - const queuesMap = this.state.get(nodeId); - if (!queuesMap) return; - for (const key in inputs) { - const queue = queuesMap.get(key); - if (!queue) continue; - queue.shift(); - } - } -} diff --git a/packages/breadboard/src/types.ts b/packages/breadboard/src/types.ts deleted file mode 100644 index 76d8e411a51..00000000000 --- a/packages/breadboard/src/types.ts +++ /dev/null @@ -1,813 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - Capability, - Edge, - GraphDescriptor, - InputValues, - KitDescriptor, - NodeDescriptor, - NodeIdentifier, - NodeTypeIdentifier, - NodeValue, - OutputValues, - StartLabel, -} from "@google-labs/breadboard-schema/graph.js"; -import { GraphLoader } from "./loader/types.js"; -import { - DataStore, - InlineDataCapabilityPart, - StoredDataCapabilityPart, -} from "./data/types.js"; -import { ManagedRunState, RunState } from "./run/types.js"; - -export type { - Capability, - CommentNode, - Edge, - GraphDescriptor, - GraphIdentifier, - GraphInlineMetadata, - InputIdentifier, - InputValues, - KitDescriptor, - KitManifest, - KitReference, - NodeConfiguration, - NodeDescriptor, - NodeIdentifier, - NodeTypeIdentifier, - NodeValue, - OutputIdentifier, - OutputValues, - SubGraphs, -} from "@google-labs/breadboard-schema/graph.js"; - -export type BehaviorSchema = - /** - * This port is deprecated and is only there because there might be graphs - * that still use it. Don't show it in the UI unless there are existing - * incoming wires. - */ - | "deprecated" - /** - * Indicates that this particular input port value should not be cached by - * the input bubbling machinery. - * Use this when you'd like to continually ask the user for the same input, - * rather that re-using cached answer (default behavior). - */ - | "transient" - /** - * Indicates that the output node should bubble up to the invoking runner, - * if any. - * This is useful for sending outputs to the user from inside of the nested - * graphs. - */ - | "bubble" - /** - * Indicates that the input our output port is a `BoardCapability`. - * @see [BoardCapability] - */ - | "board" - /** - * Indicates that the input or output port is a `StreamCapability`. - * @see [StreamCapability] - */ - | "stream" - /** - * Indicates that the input or output port is an `ErrorCapability`. - * @see [ErrorCapability] - */ - | "error" - /** - * Indicates that the input port is usually configured, rather than wired in. - */ - | "config" - /** - * Indicates that the input or output port represents base structured - * datatype containing multi-part content of a message, generated by an LLM. - * See [Content](https://ai.google.dev/api/rest/v1beta/Content) for details - * on the datatype. - */ - | "llm-content" - /** - * Indicates that the input or output port represents a JSON schema. - */ - | "json-schema" - /** - * Indicates that the input or output port represents a JSON schema that - * describes an input or output port. - */ - | "ports-spec" - /** - * Indicates that the input or output port represents an image. The image can - * be a URL or a base64 encoded image. - */ - | "image" - /** - * Indicates that the input or output represents some sort of code - */ - | "code" - /** - * Indicates that the string is a Google Drive Query. See - * https://developers.google.com/drive/api/guides/search-files. - */ - | "google-drive-query" - /** - * Indicates that the string is a Google Drive File ID. - * https://developers.google.com/drive/api/guides/about-files#characteristics - */ - | "google-drive-file-id"; - -export type Schema = { - title?: string; - description?: string; - type?: string | string[]; - properties?: Record; - required?: string[]; - format?: string; - /** - * Can be used to provide additional hints to the UI or to other parts of - * the system about behavior of this particular input/output or input/output - * port. - */ - behavior?: BehaviorSchema[]; - transient?: boolean; - enum?: string[]; - /** - * The default value of the schema. The UI can use this to pre-populate a - * field with a value, if there is no `examples` present. - */ - default?: string; - additionalProperties?: boolean | Schema; - items?: Schema | Schema[]; - minItems?: number; - /** - * Can be used by UI to pre-populate a field with a value that could be - * used as an example. - */ - examples?: string[]; -}; - -export type ErrorCapability = Capability & { - readonly kind: "error"; - readonly error?: Error; - readonly inputs?: InputValues; - readonly descriptor?: NodeDescriptor; -}; - -/** - * A capability that represents a data value passed over the wire. - * This is useful for passing inline data (base64 encoded) over the wire, as - * well as references to external resources. - */ -export type DataCapability = { - kind: "data"; -} & (InlineDataCapabilityPart | StoredDataCapabilityPart); - -/** - * The Map of queues of all outputs that were sent to a given node, - * and a map of these for all nodes. - */ -export type NodeValuesQueues = Map; -export type NodeValuesQueuesMap = Map; - -export interface QueuedNodeValuesState { - state: NodeValuesQueuesMap; - constants: NodeValuesQueuesMap; - wireOutputs(opportunities: Edge[], outputs: OutputValues): void; - getAvailableInputs(nodeId: NodeIdentifier): InputValues; - useInputs(node: NodeIdentifier, inputs: InputValues): void; -} - -export interface CompletedNodeOutput { - promiseId: symbol; - outputs: OutputValues; - newOpportunities: Edge[]; -} - -export interface TraversalResult { - descriptor: NodeDescriptor; - inputs: InputValues; - missingInputs: string[]; - current: Edge; - opportunities: Edge[]; - newOpportunities: Edge[]; - state: QueuedNodeValuesState; - outputs?: OutputValues; - partialOutputs?: OutputValues; - skip: boolean; -} - -/** - * A function that represents a type of a node in the graph. - */ -export type NodeHandlerFunction = ( - /** - * The inputs that are supplied to the node. - */ - inputs: InputValues, - /** - * The context of the node's invocation. - */ - context: NodeHandlerContext -) => Promise; - -/** - * Make sure that kit node names can't accidentally stomp over the properties - * that describe a kit. - */ -export type ReservedNodeNames = { - [key in keyof KitDescriptor]?: never; -}; - -/** - * The result of running `NodeDescriptorFunction` - */ -export type NodeDescriberResult = { - inputSchema: Schema; - outputSchema: Schema; -}; - -/** - * Context that is supplied to the `NodeDescriberFunction`. - */ -export type NodeDescriberContext = { - /** - * The base URL of the graph. - */ - base?: URL; - /** - * The graph in which the node is described. - */ - outerGraph: GraphDescriptor; - /** - * The loader that can be used to load graphs. - */ - loader?: GraphLoader; - /** - * Information about the wires currently connected to this node. - */ - wires: NodeDescriberWires; - /** - * Kits that are available in the context of the node. - */ - kits?: Kit[]; -}; - -export type NodeDescriberWires = { - // Note we only include the output port of incoming wires, and the input port - // of outgoing wires, because this object is consumed by describe functions, - // and it wouldn't make sense to ask about ports on the node we're - // implementing the describe function for, because that would be recursive. - incoming: Record; - outgoing: Record; -}; - -export type NodeDescriberPort = { - describe(): Promise; -}; - -/** - * Asks to describe a node. Can be called in multiple ways: - * - when called with no arguments, will produce the "default schema". That is, - * the inputs/outputs that are always available. - * - when called with inputs and schemas, will produce the "expected schema". - * For example, when a node changes its schema based on the actual inputs, - * it will return different schemas when inputs/schemas are supplied than - * when they are not. - */ -export type NodeDescriberFunction = ( - inputs?: InputValues, - inputSchema?: Schema, - outputSchema?: Schema, - /** - * The context in which the node is described. - */ - context?: NodeDescriberContext -) => Promise; - -export type NodeHandlerMetadata = { - /** - * Title of the node type. - */ - title?: string; - /** - * Description of the node type. - */ - description?: string; - /** - * An icon associated with this node type. - * Can be a URL or a Material Design id. - */ - icon?: string; - /** - * The URL of the node type. - */ - url?: string; - /** - * Whether or not the node is deprecated. - */ - deprecated?: boolean; - /* - * The tags associated with the node. - */ - tags?: string[]; - /** - * The documentation for the graph, expressed as a URL and optional description. - */ - help?: { - description?: string; - url: string; - }; -}; - -export type NodeHandlerObject = { - invoke: NodeHandlerFunction; - describe?: NodeDescriberFunction; - metadata?: NodeHandlerMetadata; -}; - -export type NodeHandler = NodeHandlerObject | NodeHandlerFunction; - -/** - * All known node handlers. - */ -export type NodeHandlers = ReservedNodeNames & - Record; - -export interface Kit extends KitDescriptor { - get handlers(): NodeHandlers; -} - -export type BreadboardSlotSpec = Record; - -export type RunResultType = "input" | "output"; - -export interface BreadboardRunResult { - /** - * Type of the run result. This property indicates where the board - * currently is in the `run` process. - */ - type: RunResultType; - /** - * The current node that is being visited. This property can be used to get - * information about the current node, such as its id, type, and - * configuration. - */ - node: NodeDescriptor; - /** - * Any arguments that were passed to the `input` node that triggered this - * stage. - * Usually contains `message` property, which is a friendly message - * to the user about what input is expected. - * This property is only available when `ResultRunType` is `input`. - */ - get inputArguments(): InputValues; - /** - * The input values the board is waiting for. - * Set this property to provide input values. - * This property is only available when `ResultRunType` is `input`. - */ - set inputs(input: InputValues); - /** - * the output values the board is providing. - * This property is only available when `ResultRunType` is `output`. - */ - get outputs(): OutputValues; - /** - * Current state of the underlying graph traversal. - * This property is useful for saving and restoring the state of - * graph traversal. - */ - get state(): TraversalResult; - /** - * The invocation id of the current node. This is useful for tracking - * the node within the run, similar to an "index" property in map/forEach. - * @deprecated Use `path` instead. - */ - get invocationId(): number; - /** - * The path of the current node. Supersedes the `invocationId` property. - */ - get path(): number[]; - /** - * The timestamp of when this result was issued. - */ - get timestamp(): number; - /** The current run state associated with the result. */ - get runState(): RunState | undefined; - - save(): string; -} - -export interface NodeFactory { - create( - kit: Kit | undefined, - type: NodeTypeIdentifier, - configuration?: NodeConfigurationConstructor, - id?: string - ): BreadboardNode; - getConfigWithLambda(config: ConfigOrGraph): OptionalIdConfiguration; -} - -export interface KitConstructor { - new (nodeFactory: NodeFactory): T; -} - -export type NodeSugar = ( - config?: ConfigOrGraph -) => BreadboardNode; - -export type GenericKit = Kit & { - [key in keyof T]: NodeSugar; -}; - -/** - * Validator metadata for a node. - * Used e.g. in ProbeDetails. - */ -export interface BreadboardValidatorMetadata { - description: string; -} - -/** - * A validator for a breadboard. - * For example to check integrity using information flow control. - */ -export interface BreadboardValidator { - /** - * Add a graph and validate it. - * - * @param graph The graph to validate. - * @throws Error if the graph is invalid. - */ - addGraph(graph: GraphDescriptor): void; - - /** - * Gets the validation metadata for a node. - * - * @param node Node to get metadata for. - */ - getValidatorMetadata(node: NodeDescriptor): BreadboardValidatorMetadata; - - /** - * Generate a validator for a subgraph, replacing a given node. Call - * .addGraph() on the returned validator to add and validate the subgraph. - * - * @param node The node to replace. - * @param actualInputs Actual inputs to the node (as opposed to assuming all - * inputs with * or that optional ones are present) - * @returns A validator for the subgraph. - */ - getSubgraphValidator( - node: NodeDescriptor, - actualInputs?: string[] - ): BreadboardValidator; -} - -export type GraphStartProbeData = { - graph: GraphDescriptor; - path: number[]; - timestamp: number; - edges?: EdgeResponse[]; -}; - -export type GraphStartProbeMessage = { - type: "graphstart"; - data: GraphStartProbeData; -}; - -export type GraphEndProbeData = { - path: number[]; - timestamp: number; -}; - -export type GraphEndProbeMessage = { - type: "graphend"; - data: GraphEndProbeData; -}; - -export type SkipProbeMessage = { - type: "skip"; - data: { - node: NodeDescriptor; - inputs: InputValues; - missingInputs: string[]; - path: number[]; - timestamp: number; - }; -}; - -export type NodeStartProbeMessage = { - type: "nodestart"; - data: NodeStartResponse; - state?: RunState; -}; - -export type NodeEndProbeMessage = { - type: "nodeend"; - data: NodeEndResponse; -}; - -export type EdgeProbeMessage = { - type: "edge"; - data: EdgeResponse; -}; - -export type ProbeMessage = - | GraphStartProbeMessage - | GraphEndProbeMessage - | SkipProbeMessage - | EdgeProbeMessage - | NodeStartProbeMessage - | NodeEndProbeMessage; - -/** - * Sent by the runner to supply outputs. - */ -export type OutputResponse = { - /** - * The description of the node that is providing output. - * @see [NodeDescriptor] - */ - node: NodeDescriptor; - /** - * The output values that the node is providing. - * @see [OutputValues] - */ - outputs: OutputValues; - /** - * Whether or not this input was bubbled. - */ - bubbled: boolean; - path: number[]; - timestamp: number; -}; - -/** - * Sent by the runner just before a node is about to run. - */ -export type NodeStartResponse = { - /** - * The description of the node that is about to run. - * @see [NodeDescriptor] - */ - node: NodeDescriptor; - inputs: InputValues; - path: number[]; - timestamp: number; -}; - -export type NodeEndResponse = { - node: NodeDescriptor; - inputs: InputValues; - outputs: OutputValues; - validatorMetadata?: BreadboardValidatorMetadata[]; - path: number[]; - timestamp: number; -}; - -export type EdgeResponse = { - edge: Edge; - /** - * The path of the outgoing node. - */ - from?: number[]; - /** - * The path of the incoming node. - */ - to: number[]; - timestamp: number; - value?: InputValues; -}; - -/** - * Sent by the runner to request input. - */ -export type InputResponse = { - /** - * The description of the node that is requesting input. - * @see [NodeDescriptor] - */ - node: NodeDescriptor; - /** - * The input arguments that were given to the node that is requesting input. - * These arguments typically contain the schema of the inputs that are - * expected. - * @see [InputValues] - */ - inputArguments: InputValues & { schema?: Schema }; - /** - * The path to the node in the invocation tree, from the root graph. - */ - path: number[]; - /** - * Whether or not this input was bubbled. - */ - bubbled: boolean; - /** - * The timestamp of the request. - */ - timestamp: number; -}; - -export type ErrorObject = { - /** - * The error message. Can be a string or a more detailed object. For - * example, fetch errors may return a JSON response from the server. - */ - error: string | object; - /** - * The node that threw the error. - */ - descriptor?: NodeDescriptor; - /** - * The inputs that were passed to the node that threw the error. - */ - inputs?: InputValues; -}; -/** - * Sent by the runner when an error occurs. - * Error response also indicates that the board is done running. - */ -export type ErrorResponse = { - /** - * The error message string or a more detailed error object - */ - error: string | ErrorObject; - code?: number; - timestamp: number; -}; - -// TODO: Remove extending EventTarget once new runner is converted to use -// reporting. -export interface Probe { - report?(message: ProbeMessage): Promise; -} - -export interface Breadboard extends GraphDescriptor { - input( - config?: OptionalIdConfiguration - ): BreadboardNode; - output( - config?: OptionalIdConfiguration - ): BreadboardNode; - - addEdge(edge: Edge): void; - addNode(node: NodeDescriptor): void; - addKit(ctr: KitConstructor): T; - currentBoardToAddTo(): Breadboard; - addEdgeAcrossBoards(edge: Edge, from: Breadboard, to: Breadboard): void; -} - -export type GraphDescriptorBoardCapability = { - kind: "board"; - board: GraphDescriptor; - /** - * Unresolved path to the board. Use this field to specify the path at - * compose-time that needs to be resolved at run-time. - * The path will be resolved as the inputs are received by the board, - * relative to the invoking board. - */ -}; - -export type ResolvedURLBoardCapability = { - kind: "board"; - /** - * Resolved path to the board. This field is populated at run-time as a - * result of resolving the `path` field. - */ - url: string; -}; - -export type UnresolvedPathBoardCapability = { - kind: "board"; - /** - * Unresolved path to the board. Use this field to specify the path at - * compose-time that needs to be resolved at run-time. - * The path will be resolved as the inputs are received by the board, - * relative to the invoking board. - */ - path: string; -}; - -export type BreadboardCapability = - | GraphDescriptorBoardCapability - | ResolvedURLBoardCapability - | UnresolvedPathBoardCapability; - -export interface NodeHandlerContext { - readonly board?: GraphDescriptor; - readonly descriptor?: NodeDescriptor; - readonly kits?: Kit[]; - readonly base?: URL; - /** - * The loader that can be used to load graphs. - * @see [GraphLoader] - */ - readonly loader?: GraphLoader; - readonly outerGraph?: GraphDescriptor; - readonly probe?: Probe; - readonly requestInput?: ( - name: string, - schema: Schema, - node: NodeDescriptor, - path: number[], - state: RunState - ) => Promise; - /** - * Provide output directly to the user. This will bypass the normal output - * flow and will not be passed as outputs. - * @param output - The values to provide - * @param schema - The schema to use for the output - * @returns - Promise that resolves when the output is provided - */ - readonly provideOutput?: ( - outputs: OutputValues, - descriptor: NodeDescriptor, - path: number[] - ) => Promise; - readonly invocationPath?: number[]; - readonly state?: ManagedRunState; - /** - * The `AbortSignal` that can be used to stop the board run. - */ - readonly signal?: AbortSignal; - /** - * The data store that can be used to store data across nodes. - */ - readonly store?: DataStore; -} - -export type RunArguments = NodeHandlerContext & { - /** - * Input values that will be used for bubbled inputs. If not found, a fallback - * action will be taken. For example, the web-based harness will ask the user. - */ - inputs?: InputValues; - /** - * Start label to use for the run. This is useful for specifying a particular - * node as the start of the run. If not provided, nodes without any incoming - * edges will be used. - */ - start?: StartLabel; -}; - -export interface BreadboardNode { - /** - * Wires the current node to another node. - * - * Use this method to wire nodes together. - * - * @param spec - the wiring spec. See the [wiring spec](https://github.com/breadboard-ai/breadboard/blob/main/packages/breadboard/docs/wires.md) for more details. - * @param to - the node to wire this node with. - * @returns - the current node, to enable chaining. - */ - wire( - // spec: WireSpec, - spec: string, - to: BreadboardNode - ): BreadboardNode; - - readonly id: NodeIdentifier; -} - -/** - * A node configuration that can optionally have an `$id` property. - * - * The `$id` property is used to identify the node in the board and is not - * passed to the node itself. - */ -export type OptionalIdConfiguration = { - $id?: string; -} & NodeConfigurationConstructor; - -/** - * A node configuration that optionally has nodes as values. The Node() - * constructor will remove those and turn them into wires into the node instead. - */ -export type NodeConfigurationConstructor = Record< - string, - NodeValue | BreadboardNode ->; // extends NodeConfiguration - -/** - * Syntactic sugar for node factories that accept lambdas. This allows passing - * either - * - A JS function that is a lambda function defining the board - * - A board capability, i.e. the result of calling lambda() - * - A board node, which should be a node with a `board` output - * or - * - A regular config, with a `board` property with any of the above. - * - * use `getConfigWithLambda()` to turn this into a regular config. - */ -export type ConfigOrGraph = - | OptionalIdConfiguration - | BreadboardCapability - | GraphDescriptor; diff --git a/packages/breadboard/src/utils/async-gen.ts b/packages/breadboard/src/utils/async-gen.ts deleted file mode 100644 index b369119826a..00000000000 --- a/packages/breadboard/src/utils/async-gen.ts +++ /dev/null @@ -1,202 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export type AsyncGenNext = (value: T) => Promise; -export type AsyncGenCallback = (next: AsyncGenNext) => Promise; - -// only here for historical purposes. Use asyncGen instead. -// Remove this when we're sure we don't need it anymore. -export const asyncGenOld = (callback: AsyncGenCallback) => { - type MaybeT = T | undefined; - let proceedToNext: (() => void) | undefined; - let nextCalled: (value: MaybeT) => void; - let nextThrew: (err: Error) => void; - - const next = async (result: T) => { - nextCalled(result); - return new Promise((resolve) => { - proceedToNext = resolve; - }); - }; - - return { - [Symbol.asyncIterator]() { - let waitForCallbackToCallNext: Promise; - let done = false; - const resolver = ( - resolve: (value: MaybeT) => void, - reject: (value: unknown) => void - ) => { - nextCalled = resolve; - nextThrew = reject; - }; - - waitForCallbackToCallNext = new Promise(resolver); - proceedToNext = () => { - callback(next) - .then(() => { - done = true; - nextCalled(undefined); - }) - .catch((err) => { - nextThrew(err); - }); - }; - return { - async next() { - proceedToNext && proceedToNext(); - const value = await waitForCallbackToCallNext; - waitForCallbackToCallNext = new Promise(resolver); - return { done, value }; - }, - } as AsyncIterator; - }, - }; -}; - -type QueueEntry = { - value: T | undefined; - receipt: () => void; -}; - -const noop = () => { - /* noop */ -}; - -class AsyncGenQueue { - #queue: QueueEntry[] = []; - #wroteIntoQueue = noop; - #whenQueuedUp: Promise | undefined; - #lastReceipt: (() => void) | undefined; - abort: (err: Error) => void = noop; - - constructor() { - this.#setQueuePromise(); - } - - #setQueuePromise() { - this.#whenQueuedUp = new Promise((resolve, reject) => { - this.#wroteIntoQueue = resolve; - this.abort = reject; - }); - } - - #addToQueue(entry: QueueEntry) { - this.#queue.push(entry); - if (this.#queue.length == 1) { - this.#wroteIntoQueue(); - this.#setQueuePromise(); - } - } - - async write(value: T): Promise { - return new Promise((receipt) => { - this.#addToQueue({ value, receipt }); - }); - } - - async read(): Promise> { - this.#lastReceipt && this.#lastReceipt(); - if (this.#queue.length === 0) { - await this.#whenQueuedUp; - } - const entry = this.#queue.shift(); - if (!entry) { - throw new Error("asyncGen queue should never be empty."); - } - this.#lastReceipt = entry.receipt; - if (!entry.value) { - return { done: true, value: undefined }; - } - return { done: false, value: entry.value }; - } - - close(): void { - this.#addToQueue({ value: undefined, receipt: noop }); - } -} - -class AsyncGenIterator implements AsyncIterator { - #callback: AsyncGenCallback; - #firstTime = true; - #queue = new AsyncGenQueue(); - - constructor(callback: AsyncGenCallback) { - this.#callback = callback; - } - - /** - * Called by the callback to advance to the next value. - * Roughly equivalent to "yield": - * ```ts - * yield value; - * ``` - * same as - * ```ts - * await next(value); - * ``` - * @param value - */ - async #next(value: T): Promise { - return this.#queue.write(value); - } - - async next(): Promise> { - if (this.#firstTime) { - this.#firstTime = false; - this.#callback(this.#next.bind(this)) - .then(() => { - this.#queue.close(); - }) - .catch((err) => { - this.#queue.abort(err); - }); - } - return this.#queue.read(); - } -} - -/** - * Converts async/await style code into an async generator. - * Useful when you need to combine arrow-style functions and yield. - * - * Example: - * - * ```ts - * async function* foo() { - * yield 1; - * yield* asyncGen(async (next) => { - * await next(2); - * await next(3); - * }); - * yield 4; - * } - * - * for await (const val of foo()) { - * console.log(val); - * } - * ``` - * - * This code will print: - * - * ``` - * 1 - * 2 - * 3 - * 4 - * ``` - * - * @param callback A callback that will be called with a `next` function. - * The callback should call `next` with the next value to yield. - * @returns An async generator. - */ -export const asyncGen = (callback: AsyncGenCallback) => { - return { - [Symbol.asyncIterator]() { - return new AsyncGenIterator(callback); - }, - }; -}; diff --git a/packages/breadboard/src/utils/graph-url-like.ts b/packages/breadboard/src/utils/graph-url-like.ts deleted file mode 100644 index a77da34ae74..00000000000 --- a/packages/breadboard/src/utils/graph-url-like.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * Tests if a string is Board URL-like. A "URL-like string", at least in Breadboard - * definition, has these properties: - * - it may have a distinct structure of an absolute URL, starting with a scheme - * followed by a colon, e.g. "https://example.com", "file:///path/to/file", - * "data:text/plain,Hello%2C%20World", etc. - * - it may start with a fragment identifier, e.g. "#foo", "#bar", etc. - * - * Otherwise, the string is not URL-like. - */ -export function graphUrlLike(s: string): boolean { - if (s.startsWith("#")) { - try { - new URL(s, "http://example.com"); - } catch (e) { - return false; - } - return true; - } else if (s.includes(":")) { - try { - new URL(s); - } catch (e) { - return false; - } - return true; - } else { - return false; - } -} diff --git a/packages/breadboard/src/utils/hash.ts b/packages/breadboard/src/utils/hash.ts deleted file mode 100644 index 06a2144d0c3..00000000000 --- a/packages/breadboard/src/utils/hash.ts +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { NodeValue } from "../types.js"; - -/** - * A function that computes a hash for a node value. - * This is likely an overkill for most use cases, but when we - * need to compare objects quickly, this function comes in handy. - * - * @param o - * @returns - */ -export function hash(o: NodeValue) { - let hash = 0; - const seenObjects = new WeakSet(); - const stack = [o]; - - while (stack.length) { - const current = stack.pop(); - - if (current && typeof current === "object") { - // This is probably not necessary for NodeValue, - // but just in case, let's avoid cycles. - if (seenObjects.has(current)) continue; - seenObjects.add(current); - - if (Array.isArray(current)) { - stack.push(current.length); - for (let i = current.length - 1; i >= 0; i--) { - stack.push(current[i]); - } - } else { - for (const key in current) { - const value = current[key as keyof typeof current]; - // Hash the key - hash = combineHashes(hash, hashString(key)); - stack.push(value); - } - } - } else { - // Hash primitive values directly - hash = combineHashes(hash, hashString(String(current))); - } - } - - return hash >>> 0; // Ensure unsigned 32-bit integer -} - -function combineHashes(prevHash: number, hash: number) { - // Combines two hashes using bit manipulation - return (prevHash * 31 + hash) | 0; -} - -/** - * Computes a hash for a string using the DJB2 algorithm. - * @param str - * @returns - */ -function hashString(str: string) { - let hash = 5381; - let i = str.length; - - while (i) { - hash = (hash * 33) ^ str.charCodeAt(--i); - } - - return hash >>> 0; -} diff --git a/packages/breadboard/tests/bgl/ask-for-secret.bgl.json b/packages/breadboard/tests/bgl/ask-for-secret.bgl.json deleted file mode 100644 index dfc17555a22..00000000000 --- a/packages/breadboard/tests/bgl/ask-for-secret.bgl.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "title": "Ask for secret", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "id": "secrets-f018ef7d", - "type": "secrets", - "metadata": { - "visual": { - "x": -50, - "y": -37, - "collapsed": false - }, - "title": "Secret Key", - "logLevel": "debug" - }, - "configuration": { - "keys": [ - "SECRET" - ] - } - } - ], - "edges": [] -} \ No newline at end of file diff --git a/packages/breadboard/tests/bgl/invoke-board-with-bubbling-input.bgl.json b/packages/breadboard/tests/bgl/invoke-board-with-bubbling-input.bgl.json deleted file mode 100644 index 3834bfce612..00000000000 --- a/packages/breadboard/tests/bgl/invoke-board-with-bubbling-input.bgl.json +++ /dev/null @@ -1,217 +0,0 @@ -{ - "title": "Invoke Board with Bubbling Input", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "name": { - "type": "string", - "title": "Name", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -22, - "y": -37, - "collapsed": false - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "greeting": { - "type": "string", - "title": "Greeting", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 428, - "y": 30, - "collapsed": false - } - } - }, - { - "id": "invoke-b5fe388d", - "type": "invoke", - "metadata": { - "visual": { - "x": 125, - "y": -48, - "collapsed": false - }, - "title": "Invoker", - "logLevel": "debug" - }, - "configuration": { - "$board": "#382969d5-0908-4367-b09e-95d8b351c39b" - } - }, - { - "id": "promptTemplate-f586d280", - "type": "promptTemplate", - "metadata": { - "visual": { - "x": 175, - "y": 105, - "collapsed": false - }, - "title": "Wrapper", - "logLevel": "debug" - }, - "configuration": { - "template": "Greeting is: \"{{greeting}}\"" - } - } - ], - "edges": [ - { - "from": "input", - "to": "invoke-b5fe388d", - "out": "name", - "in": "name" - }, - { - "from": "invoke-b5fe388d", - "to": "promptTemplate-f586d280", - "out": "greeting", - "in": "greeting" - }, - { - "from": "promptTemplate-f586d280", - "to": "output", - "out": "prompt", - "in": "greeting" - } - ], - "graphs": { - "382969d5-0908-4367-b09e-95d8b351c39b": { - "title": "Template Maker", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "name": { - "type": "string", - "title": "Name", - "examples": [] - }, - "location": { - "type": "string", - "title": "Location", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -191, - "y": -11, - "collapsed": false - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "greeting": { - "type": "string", - "title": "Greeting", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 215, - "y": 8, - "collapsed": false - } - } - }, - { - "id": "promptTemplate-81f85b70", - "type": "promptTemplate", - "metadata": { - "visual": { - "x": 12, - "y": 7, - "collapsed": false - }, - "title": "Make Template", - "logLevel": "debug" - }, - "configuration": { - "template": "Hello, {{name}} from {{location}}!" - } - } - ], - "edges": [ - { - "from": "input", - "to": "promptTemplate-81f85b70", - "out": "name", - "in": "name" - }, - { - "from": "input", - "to": "promptTemplate-81f85b70", - "out": "location", - "in": "location" - }, - { - "from": "promptTemplate-81f85b70", - "to": "output", - "out": "prompt", - "in": "greeting" - } - ], - "metadata": { - "tags": [ - "tool" - ], - "comments": [] - }, - "url": "file://fsapi~bgl/invoke-board-with-bubbling-input.bgl.json#382969d5-0908-4367-b09e-95d8b351c39b" - } - }, - "metadata": { - "tags": [ - "tool" - ] - } -} \ No newline at end of file diff --git a/packages/breadboard/tests/bgl/just-output.bgl.json b/packages/breadboard/tests/bgl/just-output.bgl.json deleted file mode 100644 index 816c8b5286b..00000000000 --- a/packages/breadboard/tests/bgl/just-output.bgl.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "title": "just output", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "end": { - "type": "string", - "title": "The End", - "examples": [] - } - }, - "type": "object", - "required": [] - }, - "end": "END" - }, - "metadata": { - "visual": { - "x": 77, - "y": -11, - "collapsed": false - } - } - } - ], - "edges": [] -} \ No newline at end of file diff --git a/packages/breadboard/tests/bgl/many-inputs.bgl.json b/packages/breadboard/tests/bgl/many-inputs.bgl.json deleted file mode 100644 index 7a131041cc0..00000000000 --- a/packages/breadboard/tests/bgl/many-inputs.bgl.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "title": "many inputs", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "text1": { - "type": "string", - "title": "Text", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -64, - "y": 0, - "collapsed": false - }, - "title": "One", - "logLevel": "debug" - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "text-one": { - "type": "string", - "title": "Text One", - "examples": [] - }, - "text-two": { - "type": "string", - "title": "Text Two", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 215, - "y": 57, - "collapsed": false - } - } - }, - { - "id": "input-3c20cd3f", - "type": "input", - "metadata": { - "visual": { - "x": -63, - "y": 111, - "collapsed": false - }, - "title": "Two", - "logLevel": "debug" - }, - "configuration": { - "schema": { - "properties": { - "text2": { - "type": "string", - "title": "Text", - "examples": [] - } - }, - "type": "object", - "required": [] - } - } - } - ], - "edges": [ - { - "from": "input-3c20cd3f", - "to": "output", - "out": "text2", - "in": "text-two" - }, - { - "from": "input", - "to": "output", - "out": "text1", - "in": "text-one" - } - ], - "description": "", - "metadata": { - "tags": [], - "comments": [] - } -} \ No newline at end of file diff --git a/packages/breadboard/tests/bgl/many-outputs.bgl.json b/packages/breadboard/tests/bgl/many-outputs.bgl.json deleted file mode 100644 index 43567fbefa9..00000000000 --- a/packages/breadboard/tests/bgl/many-outputs.bgl.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "title": "many-outputs", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "start": { - "type": "string", - "title": "Start", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -159, - "y": 89, - "collapsed": false - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "one": { - "type": "string", - "title": "One", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 213, - "y": -24, - "collapsed": false - }, - "title": "One", - "logLevel": "debug" - } - }, - { - "type": "output", - "id": "output-83a8ab5e", - "configuration": { - "schema": { - "properties": { - "two": { - "type": "string", - "title": "Two", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 233, - "y": 169, - "collapsed": false - }, - "title": "Two", - "logLevel": "debug" - } - }, - { - "id": "runJavascript-fe3c9a41", - "type": "runJavascript", - "metadata": { - "visual": { - "x": 8, - "y": 44, - "collapsed": false - }, - "title": "Split", - "logLevel": "debug" - }, - "configuration": { - "code": "function run({start}) {\n return {\n \"one\": start,\n \"two\": start,\n }\n}", - "name": "run", - "raw": true - } - } - ], - "edges": [ - { - "from": "input", - "to": "runJavascript-fe3c9a41", - "out": "start", - "in": "start" - }, - { - "from": "runJavascript-fe3c9a41", - "to": "output", - "out": "one", - "in": "one" - }, - { - "from": "runJavascript-fe3c9a41", - "to": "output-83a8ab5e", - "out": "two", - "in": "two" - } - ], - "metadata": { - "comments": [] - } -} \ No newline at end of file diff --git a/packages/breadboard/tests/bgl/map-with-bubbling-inputs.bgl.json b/packages/breadboard/tests/bgl/map-with-bubbling-inputs.bgl.json deleted file mode 100644 index f6c83e19330..00000000000 --- a/packages/breadboard/tests/bgl/map-with-bubbling-inputs.bgl.json +++ /dev/null @@ -1,205 +0,0 @@ -{ - "title": "Map with bubbling inputs", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "greetings": { - "type": "string", - "title": "Greetings", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 200, - "y": -35, - "collapsed": false - } - } - }, - { - "id": "runJavascript-0e58b5d0", - "type": "runJavascript", - "metadata": { - "visual": { - "x": -212, - "y": -89, - "collapsed": false - }, - "title": "Generate Names", - "logLevel": "debug" - }, - "configuration": { - "code": "function run() {\n return [\"Bob\", \"Alice\"];\n}", - "name": "run", - "raw": false - } - }, - { - "id": "map-6088d0ca", - "type": "map", - "metadata": { - "visual": { - "x": -16, - "y": -141, - "collapsed": false - }, - "title": "Map", - "logLevel": "debug" - }, - "configuration": { - "board": "#1f8fd904-53c6-4cc4-b1d0-53446142a7c7" - } - }, - { - "id": "runJavascript-fa4db3af", - "type": "runJavascript", - "metadata": { - "visual": { - "x": 158, - "y": -187, - "collapsed": false - }, - "title": "Stringify", - "logLevel": "debug" - }, - "configuration": { - "code": "function run({list}) {\n return list.map((item) => item.greeting).join(\"\\n\");\n}", - "name": "run", - "raw": false - } - } - ], - "edges": [ - { - "from": "runJavascript-0e58b5d0", - "to": "map-6088d0ca", - "out": "result", - "in": "list" - }, - { - "from": "map-6088d0ca", - "to": "runJavascript-fa4db3af", - "out": "list", - "in": "list" - }, - { - "from": "runJavascript-fa4db3af", - "to": "output", - "out": "result", - "in": "greetings" - } - ], - "graphs": { - "1f8fd904-53c6-4cc4-b1d0-53446142a7c7": { - "title": "Template Maker", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "location": { - "type": "string", - "title": "Location", - "examples": [] - }, - "item": { - "type": "string", - "title": "Name", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -152, - "y": -29, - "collapsed": false - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "greeting": { - "type": "string", - "title": "Greeting", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 241, - "y": -37, - "collapsed": false - } - } - }, - { - "id": "promptTemplate-81f85b70", - "type": "promptTemplate", - "metadata": { - "visual": { - "x": 38, - "y": -38, - "collapsed": false - }, - "title": "Make Template", - "logLevel": "debug" - }, - "configuration": { - "template": "Hello, {{name}} from {{location}}!" - } - } - ], - "edges": [ - { - "from": "input", - "to": "promptTemplate-81f85b70", - "in": "location", - "out": "location" - }, - { - "from": "promptTemplate-81f85b70", - "to": "output", - "in": "greeting", - "out": "prompt" - }, - { - "from": "input", - "to": "promptTemplate-81f85b70", - "out": "item", - "in": "name" - } - ], - "metadata": { - "comments": [] - }, - "url": "file://fsapi~bgl/map-with-bubbling-inputs.bgl.json#1f8fd904-53c6-4cc4-b1d0-53446142a7c7" - } - } -} \ No newline at end of file diff --git a/packages/breadboard/tests/bgl/multi-level-invoke.bgl.json b/packages/breadboard/tests/bgl/multi-level-invoke.bgl.json deleted file mode 100644 index a6cd3b2e6c9..00000000000 --- a/packages/breadboard/tests/bgl/multi-level-invoke.bgl.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "title": "Multi-level Invoke", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "id": "invoke-d5aa6bf1", - "type": "invoke", - "metadata": { - "visual": { - "x": -82, - "y": 51, - "collapsed": false - }, - "title": "Invoke Everything", - "logLevel": "debug" - }, - "configuration": { - "$board": "./invoke-board-with-bubbling-input.bgl.json" - } - }, - { - "id": "output-2caa5d82", - "type": "output", - "metadata": { - "visual": { - "x": 123, - "y": 49, - "collapsed": false - }, - "title": "Out", - "logLevel": "debug" - }, - "configuration": { - "schema": { - "properties": { - "greeting": { - "type": "string", - "title": "Greeting", - "examples": [] - } - }, - "type": "object", - "required": [] - } - } - } - ], - "edges": [ - { - "from": "invoke-d5aa6bf1", - "to": "output-2caa5d82", - "out": "greeting", - "in": "greeting" - } - ] -} diff --git a/packages/breadboard/tests/bgl/prompt-template.bgl.json b/packages/breadboard/tests/bgl/prompt-template.bgl.json deleted file mode 100644 index 9b2c0d568a3..00000000000 --- a/packages/breadboard/tests/bgl/prompt-template.bgl.json +++ /dev/null @@ -1,206 +0,0 @@ -{ - "title": "Prompt Template", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": {}, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -210, - "y": -319, - "collapsed": "expanded" - }, - "tags": [ - { - "type": "start", - "label": "default" - } - ] - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "prompt": { - "type": "string", - "title": "Prompt", - "examples": [], - "format": "multiline" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 452, - "y": -302, - "collapsed": "expanded" - } - } - }, - { - "id": "runJavascript-2655506c", - "type": "runJavascript", - "metadata": { - "visual": { - "x": 34, - "y": -361, - "collapsed": "expanded" - }, - "title": "Substitute Placeholders", - "logLevel": "debug" - }, - "configuration": { - "code": "function run({template, ... inputs}) {\n const toId = (param) => `p-${param}`;\n const toName = (id) => id.slice(2);\n\n const stringify = (value) => {\n if (typeof value === \"string\") return value;\n if (value === undefined) return \"undefined\";\n return JSON.stringify(value, null, 2);\n };\n \n const substitute = (template, values) => {\n return Object.entries(values).reduce(\n (acc, [key, value]) => acc.replace(`{{${key}}}`, stringify(value)),\n template\n );\n };\n \n const parametersFromTemplate = (template) => {\n if (!template) return [];\n const matches = template.matchAll(/{{(?[\\w-]+)}}/g);\n const parameters = Array.from(matches).map(\n (match) => match.groups?.name || \"\"\n );\n const unique = Array.from(new Set(parameters));\n return unique;\n };\n \n const parameters = parametersFromTemplate(template);\n if (!parameters.length) return template;\n\n const substitutes = parameters.reduce((acc, parameter) => {\n if (inputs[toId(parameter)] === undefined)\n throw new Error(`Input is missing parameter \"${parameter}\"`);\n return { ...acc, [parameter]: inputs[toId(parameter)] };\n }, {});\n\n const prompt = substitute(template, substitutes);\n console.log(\"PROMPT\", prompt);\n return prompt;\n}", - "name": "run", - "raw": false - } - } - ], - "edges": [ - { - "from": "input", - "to": "runJavascript-2655506c", - "out": "*", - "in": "" - }, - { - "from": "runJavascript-2655506c", - "to": "output", - "out": "result", - "in": "prompt" - } - ], - "metadata": { - "comments": [], - "describer": "#7f933743-00fa-4047-9e18-84714adf84a0" - }, - "graphs": { - "7f933743-00fa-4047-9e18-84714adf84a0": { - "title": "Describer", - "description": "Custom Describer for the Prompt Template", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "metadata": { - "visual": { - "x": -87, - "y": 45.00000000000006, - "collapsed": "expanded" - }, - "tags": [ - { - "type": "start", - "label": "default" - } - ] - } - }, - { - "id": "runJavascript-4e04e982", - "type": "runJavascript", - "metadata": { - "visual": { - "x": 176, - "y": -62.99999999999994, - "collapsed": "expanded" - }, - "title": "Schema from Inputs", - "logLevel": "debug" - }, - "configuration": { - "outputSchema": { - "properties": { - "outputSchema": { - "type": "object", - "title": "Output Schema", - "examples": [] - }, - "inputSchema": { - "type": "object", - "title": "Input Schema", - "examples": [] - } - }, - "type": "object", - "required": [] - }, - "code": "function run({ template }) {\n const toId = (param) => `p-${param}`;\n const parametersFromTemplate = (template) => {\n if (!template) return [];\n const matches = template.matchAll(/{{(?[\\w-]+)}}/g);\n const parameters = Array.from(matches).map(\n (match) => match.groups?.name || \"\"\n );\n const unique = Array.from(new Set(parameters));\n return unique;\n };\n\n const parameters = parametersFromTemplate(template);\n\n const required = [ \"template\", ...parameters.map(toId)];\n\n const inputSchema = {\n type: \"object\",\n properties: {\n ...Object.fromEntries(\n parameters.map((parameter) => [\n toId(parameter),\n {\n title: parameter,\n description: `The value to substitute for the parameter \"${parameter}\"`,\n type: \"string\",\n },\n ])\n ),\n template: {\n title: \"Template\",\n description: \"The template string to substitute the parameters into\",\n type: \"string\",\n format: \"multiline\",\n },\n },\n required,\n };\n\n const outputSchema = {\n type: \"object\",\n properties: {\n prompt: {\n type: \"string\",\n format: \"multiline\",\n title: \"Prompt\",\n description: \"The prompt string with the parameters substituted\", \n },\n },\n };\n\n return {\n inputSchema,\n outputSchema,\n };\n}\n", - "name": "run", - "raw": true - } - }, - { - "id": "output-acc3ef03", - "type": "output", - "metadata": { - "visual": { - "x": 645.4438806230096, - "y": -42.74531749166499, - "collapsed": "expanded" - }, - "title": "Schemas", - "logLevel": "debug" - }, - "configuration": { - "schema": { - "properties": { - "inputSchema": { - "type": "object", - "title": "Input Schema", - "examples": [] - }, - "outputSchema": { - "type": "object", - "title": "Output Schema", - "examples": [] - } - }, - "type": "object", - "required": [] - } - } - } - ], - "edges": [ - { - "from": "input", - "to": "runJavascript-4e04e982", - "in": "", - "out": "*" - }, - { - "from": "runJavascript-4e04e982", - "to": "output-acc3ef03", - "in": "inputSchema", - "out": "inputSchema" - }, - { - "from": "runJavascript-4e04e982", - "to": "output-acc3ef03", - "in": "outputSchema", - "out": "outputSchema" - } - ], - "metadata": { - "comments": [] - } - } - } -} diff --git a/packages/breadboard/tests/bgl/simple.bgl.json b/packages/breadboard/tests/bgl/simple.bgl.json deleted file mode 100644 index f5ab470e3cc..00000000000 --- a/packages/breadboard/tests/bgl/simple.bgl.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "title": "simple", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "text": { - "type": "string", - "title": "Text", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -180, - "y": 62, - "collapsed": false - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "text": { - "type": "string", - "title": "Text", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 215, - "y": 57, - "collapsed": false - } - } - } - ], - "edges": [ - { - "from": "input", - "to": "output", - "out": "text", - "in": "text" - } - ] -} \ No newline at end of file diff --git a/packages/breadboard/tests/board.ts b/packages/breadboard/tests/board.ts deleted file mode 100644 index 16071573c63..00000000000 --- a/packages/breadboard/tests/board.ts +++ /dev/null @@ -1,174 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { Board } from "../src/board.js"; -import type { GraphDescriptor, InputValues } from "../src/types.js"; -import { TestKit } from "./helpers/_test-kit.js"; -import breadboardSchema from "@google-labs/breadboard-schema/breadboard.schema.json" with { type: "json" }; -import { invokeGraph, runGraph } from "../src/index.js"; - -test("correctly passes inputs and outputs to included boards", async (t) => { - const nestedBoard = new Board(); - const nestedKit = nestedBoard.addKit(TestKit); - nestedBoard - .input() - .wire( - "hello->", - nestedKit.noop().wire("hello->", nestedBoard.output({ $id: "output" })) - ); - - const board = new Board(); - const kit = board.addKit(TestKit); - board - .input() - .wire( - "hello->", - kit - .include({ graph: nestedBoard as GraphDescriptor } as InputValues) - .wire("hello->", board.output()) - ); - - const result = await invokeGraph( - board, - { hello: "world" }, - { kits: [nestedKit] } - ); - t.deepEqual(result, { hello: "world" }); -}); - -test("correctly passes inputs and outputs to included boards with a probe", async (t) => { - const nestedBoard = new Board(); - const nestedKit = nestedBoard.addKit(TestKit); - nestedBoard - .input() - .wire( - "hello->", - nestedKit.noop().wire("hello->", nestedBoard.output({ $id: "output" })) - ); - - const board = new Board(); - const kit = board.addKit(TestKit); - board - .input() - .wire( - "hello->", - kit - .include({ graph: nestedBoard as GraphDescriptor } as InputValues) - .wire("hello->", board.output()) - ); - - const result = await invokeGraph( - board, - { hello: "world" }, - { kits: [nestedKit] } - ); - t.deepEqual(result, { hello: "world" }); -}); - -test("allows pausing and resuming the board", async (t) => { - let result; - const board = new Board(); - const kit = board.addKit(TestKit); - const input = board.input(); - input.wire("<-", kit.noop()); - input.wire("*->", kit.noop().wire("*->", board.output().wire("*->", input))); - { - for await (const stop of runGraph(board, { kits: [kit] }, result)) { - t.is(stop.type, "input"); - result = stop; - break; - } - } - { - for await (const stop of runGraph(board, { kits: [kit] }, result?.state)) { - t.is(stop.type, "output"); - result = stop; - break; - } - } - { - for await (const stop of runGraph(board, { kits: [kit] }, result?.state)) { - t.is(stop.type, "input"); - result = stop; - break; - } - } -}); - -test("throws when incorrectly wiring different boards", async (t) => { - const board = new Board(); - const board2 = new Board(); - const input = board.input(); - const output = board2.output(); - await t.throwsAsync( - async () => { - input.wire("foo->.", output); - }, - { message: "Across board wires: From must be parent of to" } - ); - await t.throwsAsync( - async () => { - input.wire("foo<-", output); - }, - { message: "Across board wires: Must be constant for now" } - ); -}); - -test("when $error is set, all other outputs are ignored, named", async (t) => { - const board = new Board(); - const kit = board.addKit(TestKit); - const noop = kit.noop({ foo: 1, $error: { kind: "error" } }); - noop.wire("foo->", board.output()); - noop.wire( - "$error->", - // extra noop so that the above output would be used first - kit.noop().wire("$error->", board.output()) - ); - const result = await invokeGraph( - board, - {}, - { - kits: [kit], - } - ); - t.is(result.foo, undefined); - t.like(result.$error, { kind: "error" }); -}); - -test("when $error is set, all other outputs are ignored, with *", async (t) => { - const board = new Board(); - const kit = board.addKit(TestKit); - const noop = kit.noop({ foo: 1, $error: { kind: "error" } }); - const output = board.output(); - noop.wire("*->", output); - noop.wire("$error->", output); - const result = await invokeGraph(board, {}, { kits: [kit] }); - t.is(result.foo, undefined); - t.like(result.$error, { kind: "error" }); -}); - -test("expect schema to be valid URI", async (t) => { - const schemaId = breadboardSchema.$id; - t.truthy(schemaId); - t.regex(schemaId, /^https?:\/\//); -}); - -test("board contains a schema by default", async (t) => { - const board = new Board(); - const serialized = JSON.parse(JSON.stringify(board)); - t.is(serialized.$schema, breadboardSchema.$id); -}); - -test("can set a custom schema", async (t) => { - const customSchema = - "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/schema/breadboard.schema.json"; - const board = new Board({ - $schema: customSchema, - }); - const serialized = JSON.parse(JSON.stringify(board)); - t.is(serialized.$schema, customSchema); -}); diff --git a/packages/breadboard/tests/bubble.ts b/packages/breadboard/tests/bubble.ts deleted file mode 100644 index 13baa77be7a..00000000000 --- a/packages/breadboard/tests/bubble.ts +++ /dev/null @@ -1,263 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { - InputSchemaReader, - createBubbleHandler, - createErrorMessage, -} from "../src/bubble.js"; -import { GraphDescriptor, NodeHandlerContext } from "../src/types.js"; - -test("InputSchemaReader works as expected", async (t) => { - { - const requester = new InputSchemaReader( - {}, - { - schema: { - type: "object", - properties: { - a: { type: "string" }, - b: { type: "number" }, - }, - required: ["a"], - }, - }, - [] - ); - const inputs: unknown[] = []; - const result = await requester.read(async (name, schema, required) => { - inputs.push({ name, schema, required }); - return name; - }); - t.deepEqual(inputs, [ - { name: "a", schema: { type: "string" }, required: true }, - { name: "b", schema: { type: "number" }, required: false }, - ]); - t.deepEqual(result, { a: "a", b: "b" }); - } - { - const requester = new InputSchemaReader({}, {}, []); - const inputs: unknown[] = []; - const result = await requester.read(async (name, schema, required) => { - inputs.push({ name, schema, required }); - return name; - }); - t.deepEqual(inputs, []); - t.deepEqual(result, {}); - } - { - const requester = new InputSchemaReader({}, { schema: {} }, []); - const inputs: unknown[] = []; - const result = await requester.read(async (name, schema, required) => { - inputs.push({ name, schema, required }); - return name; - }); - t.deepEqual(inputs, []); - t.deepEqual(result, {}); - } - { - const requester = new InputSchemaReader( - {}, - { - schema: { - type: "object", - properties: { - a: { type: "string" }, - b: { type: "number" }, - }, - }, - }, - [] - ); - const inputs: unknown[] = []; - const result = await requester.read(async (name, schema, required) => { - inputs.push({ name, schema, required }); - return name; - }); - t.deepEqual(inputs, [ - { name: "a", schema: { type: "string" }, required: false }, - { name: "b", schema: { type: "number" }, required: false }, - ]); - t.deepEqual(result, { a: "a", b: "b" }); - } -}); - -test("InputSchemaReader correctly handles existing outputs", async (t) => { - { - const requester = new InputSchemaReader( - { a: "existingA" }, - { - schema: { - type: "object", - properties: { - a: { type: "string" }, - b: { type: "number" }, - }, - }, - }, - [] - ); - const inputs: unknown[] = []; - const result = await requester.read(async (name, schema, required) => { - inputs.push({ name, schema, required }); - return name; - }); - t.deepEqual(inputs, [ - { name: "b", schema: { type: "number" }, required: false }, - ]); - t.deepEqual(result, { a: "existingA", b: "b" }); - } - { - const requester = new InputSchemaReader( - { a: "existingA", c: "existingC" }, - { - schema: { - type: "object", - properties: { - a: { type: "string" }, - b: { type: "number" }, - }, - required: ["a"], - }, - }, - [] - ); - const inputs: unknown[] = []; - const result = await requester.read(async (name, schema, required) => { - inputs.push({ name, schema, required }); - return name; - }); - t.deepEqual(inputs, [ - { name: "b", schema: { type: "number" }, required: false }, - ]); - t.deepEqual(result, { a: "existingA", b: "b", c: "existingC" }); - } - { - const requester = new InputSchemaReader( - { a: "existingA", c: "existingC" }, - {}, - [] - ); - const inputs: unknown[] = []; - const result = await requester.read(async (name, schema, required) => { - inputs.push({ name, schema, required }); - return name; - }); - t.deepEqual(inputs, []); - t.deepEqual(result, { a: "existingA", c: "existingC" }); - } - { - const requester = new InputSchemaReader( - { a: "existingA", c: "existingC" }, - { schema: {} }, - [] - ); - const inputs: unknown[] = []; - const result = await requester.read(async (name, schema, required) => { - inputs.push({ name, schema, required }); - return name; - }); - t.deepEqual(inputs, []); - t.deepEqual(result, { a: "existingA", c: "existingC" }); - } -}); - -test("createErrorMessage makes sensible messages", (t) => { - t.deepEqual( - createErrorMessage("foo", {}, true), - 'Missing required input "foo".' - ); - t.deepEqual(createErrorMessage("foo", {}, false), 'Missing input "foo".'); - t.deepEqual( - createErrorMessage("foo", { title: "Foo", url: "url goes here" }, true), - 'Missing required input "foo" for board "Foo".' - ); - t.deepEqual( - createErrorMessage("foo", { url: "url goes here" }, true), - 'Missing required input "foo" for board "url goes here".' - ); - t.deepEqual( - createErrorMessage("foo", { url: "url goes here" }, false), - 'Missing input "foo" for board "url goes here".' - ); -}); - -test("createBubbleHandler works as expected", async (t) => { - const descriptor = { id: "id", type: "type" }; - { - const handler = createBubbleHandler({}, {}, descriptor, []); - await t.throwsAsync( - handler("foo", { type: "string" }, true, []), - undefined, - 'Missing required input "foo".' - ); - await t.throwsAsync( - handler("foo", { type: "string" }, false, []), - undefined, - 'Missing input "foo".' - ); - t.deepEqual( - await handler("foo", { type: "string", default: "bar" }, false, []), - "bar" - ); - } - { - const handler = createBubbleHandler( - {}, - { - board: { title: "Foo" } as GraphDescriptor, - }, - descriptor, - [] - ); - await t.throwsAsync( - handler("foo", { type: "string" }, true, []), - undefined, - 'Missing required input "foo" for board "Foo".' - ); - } - { - const handler = createBubbleHandler( - {}, - { - requestInput: async () => "bar", - } satisfies NodeHandlerContext, - descriptor, - [] - ); - t.deepEqual(await handler("foo", { type: "string" }, false, []), "bar"); - await t.throwsAsync( - handler("foo", { type: "string" }, true, []), - undefined, - 'Missing required input "foo".' - ); - } - { - const handler = createBubbleHandler({}, {}, descriptor, []); - t.deepEqual( - await handler("foo", { type: "string", default: "bar" }, false, []), - "bar" - ); - t.deepEqual( - await handler("foo", { type: "boolean", default: "false" }, false, []), - false - ); - t.deepEqual( - await handler("foo", { type: "array", default: "[]" }, false, []), - [] - ); - t.deepEqual( - await handler( - "foo", - { type: "object", default: '{ "foo": "bar" }' }, - false, - [] - ), - { foo: "bar" } - ); - } -}); diff --git a/packages/breadboard/tests/data/describe-start-tag-no-run.json b/packages/breadboard/tests/data/describe-start-tag-no-run.json deleted file mode 100644 index 376039090c6..00000000000 --- a/packages/breadboard/tests/data/describe-start-tag-no-run.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "edges": [ - { - "from": "node-b", - "out": "text", - "to": "node-c", - "in": "data" - }, - { - "from": "node-a", - "out": "text", - "to": "node-d", - "in": "data" - } - ], - "nodes": [ - { "id": "node-a", "type": "input" }, - { - "id": "node-b", - "type": "input", - "metadata": { - "tags": [ - { - "type": "start", - "label": "describe" - } - ] - } - }, - { "id": "node-c", "type": "output" }, - { "id": "node-d", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [], - "sequence": [], - "throws": true -} diff --git a/packages/breadboard/tests/data/describe-start-tag-run.json b/packages/breadboard/tests/data/describe-start-tag-run.json deleted file mode 100644 index a09a443a100..00000000000 --- a/packages/breadboard/tests/data/describe-start-tag-run.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "edges": [ - { - "from": "node-b", - "out": "text", - "to": "node-c", - "in": "data" - }, - { - "from": "node-a", - "out": "text", - "to": "node-d", - "in": "data" - } - ], - "nodes": [ - { "id": "node-a", "type": "input" }, - { - "id": "node-b", - "type": "input", - "metadata": { - "tags": [ - { - "type": "start", - "label": "describe" - } - ] - } - }, - { "id": "node-c", "type": "output" }, - { "id": "node-d", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [{ "data": "foo" }], - "sequence": ["node-b", "node-c"], - "start": "describe" -} diff --git a/packages/breadboard/tests/data/empty-string.json b/packages/breadboard/tests/data/empty-string.json deleted file mode 100644 index 81c7c22e5aa..00000000000 --- a/packages/breadboard/tests/data/empty-string.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "edges": [ - { - "from": "input-1", - "out": "text", - "to": "output-1", - "in": "text" - } - ], - "nodes": [ - { "id": "input-1", "type": "input" }, - { "id": "output-1", "type": "output" } - ], - "inputs": { "text": "" }, - "outputs": [{ "text": "" }], - "sequence": ["input-1", "output-1"] -} diff --git a/packages/breadboard/tests/data/error-caught.json b/packages/breadboard/tests/data/error-caught.json deleted file mode 100644 index 808febbbc2d..00000000000 --- a/packages/breadboard/tests/data/error-caught.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "edges": [ - { - "from": "node-a", - "out": "text", - "to": "node-c", - "in": "description" - }, - { - "from": "node-a", - "out": "$error", - "to": "node-b", - "in": "$error" - }, - { - "from": "node-b", - "out": "$error", - "to": "node-c", - "in": "explanation" - } - ], - "nodes": [ - { "id": "node-a", "type": "error" }, - { "id": "node-b", "type": "output" }, - { "id": "node-c", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [ - { - "$error": { - "kind": "error", - "descriptor": { "id": "node-a", "type": "error" }, - "error": "instanceof Error", - "inputs": {} - } - } - ], - "sequence": ["node-a", "node-b"], - "throws": false -} diff --git a/packages/breadboard/tests/data/exception-not-caught.json b/packages/breadboard/tests/data/exception-not-caught.json deleted file mode 100644 index 7e014d8e769..00000000000 --- a/packages/breadboard/tests/data/exception-not-caught.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "edges": [ - { - "from": "node-a", - "out": "text", - "to": "node-c", - "in": "description" - }, - { - "from": "node-a", - "out": "text", - "to": "node-b", - "in": "text" - }, - { - "from": "node-b", - "out": "text", - "to": "node-c", - "in": "context" - } - ], - "nodes": [ - { "id": "node-a", "type": "throw" }, - { "id": "node-b", "type": "noop" }, - { "id": "node-c", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [], - "sequence": ["node-a"], - "throws": true -} diff --git a/packages/breadboard/tests/data/invalid-node.json b/packages/breadboard/tests/data/invalid-node.json deleted file mode 100644 index 80ead0ab24e..00000000000 --- a/packages/breadboard/tests/data/invalid-node.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "edges": [ - { - "from": "invalid", - "out": "text", - "to": "output-1", - "in": "text" - } - ], - "nodes": [ - { "id": "input-1", "type": "input" }, - { "id": "output-1", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [], - "sequence": ["input-1"] -} diff --git a/packages/breadboard/tests/data/no-entry.json b/packages/breadboard/tests/data/no-entry.json deleted file mode 100644 index 285f2d55297..00000000000 --- a/packages/breadboard/tests/data/no-entry.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "edges": [ - { - "from": "input-1", - "out": "text", - "to": "output-1", - "in": "text" - }, - { - "from": "output-1", - "out": "text", - "to": "input-1", - "in": "text" - } - ], - "nodes": [ - { "id": "input-1", "type": "input" }, - { "id": "output-1", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [], - "sequence": [], - "throws": true -} diff --git a/packages/breadboard/tests/data/one-entry.json b/packages/breadboard/tests/data/one-entry.json deleted file mode 100644 index 93fbf5e201e..00000000000 --- a/packages/breadboard/tests/data/one-entry.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "edges": [ - { - "from": "node-a", - "out": "text", - "to": "node-c", - "in": "description" - }, - { - "from": "node-a", - "out": "text", - "to": "node-b", - "in": "text" - }, - { - "from": "node-b", - "out": "text", - "to": "node-c", - "in": "context" - } - ], - "nodes": [ - { "id": "node-a", "type": "input" }, - { "id": "node-b", "type": "noop" }, - { "id": "node-c", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [{ "context": "foo", "description": "foo" }], - "sequence": ["node-a", "node-b", "node-c"] -} diff --git a/packages/breadboard/tests/data/optional-edges-2.json b/packages/breadboard/tests/data/optional-edges-2.json deleted file mode 100644 index d2936655852..00000000000 --- a/packages/breadboard/tests/data/optional-edges-2.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "title": "Optional edges; skip for now as behavior is underdefined", - "edges": [ - { - "from": "node-a", - "out": "text", - "to": "node-b", - "in": "text" - }, - { - "from": "node-a", - "out": "text", - "to": "node-c", - "in": "description", - "optional": true - }, - { - "from": "node-b", - "out": "text", - "to": "node-c", - "in": "context", - "optional": true - } - ], - "nodes": [ - { "id": "node-a", "type": "input" }, - { "id": "node-b", "type": "noop" }, - { "id": "node-c", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [{ "context": "foo", "description": "foo" }, {}], - "sequence": ["node-a", "node-b", "node-c", "node-c"] -} diff --git a/packages/breadboard/tests/data/optional-edges.json b/packages/breadboard/tests/data/optional-edges.json deleted file mode 100644 index 0460b7b8c5a..00000000000 --- a/packages/breadboard/tests/data/optional-edges.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "title": "Optional edges; skip for now as behavior is underdefined", - "edges": [ - { - "from": "node-a", - "out": "text", - "to": "node-c", - "in": "description", - "optional": true - }, - { - "from": "node-a", - "out": "text", - "to": "node-b", - "in": "text" - }, - { - "from": "node-b", - "out": "text", - "to": "node-c", - "in": "context", - "optional": true - } - ], - "nodes": [ - { "id": "node-a", "type": "input" }, - { "id": "node-b", "type": "noop" }, - { "id": "node-c", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [{ "description": "foo" }, { "context": "foo" }], - "sequence": ["node-a", "node-c", "node-b", "node-c"] -} diff --git a/packages/breadboard/tests/data/passing-all.json b/packages/breadboard/tests/data/passing-all.json deleted file mode 100644 index 47891ebf6cb..00000000000 --- a/packages/breadboard/tests/data/passing-all.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "edges": [ - { - "from": "input-1", - "out": "*", - "to": "output-1" - } - ], - "nodes": [ - { "id": "input-1", "type": "input" }, - { "id": "output-1", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [{ "text": "foo" }], - "sequence": ["input-1", "output-1"] -} diff --git a/packages/breadboard/tests/data/passing-none.json b/packages/breadboard/tests/data/passing-none.json deleted file mode 100644 index 2e69b99790a..00000000000 --- a/packages/breadboard/tests/data/passing-none.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "edges": [ - { - "from": "input-1", - "to": "output-1" - } - ], - "nodes": [ - { "id": "input-1", "type": "input" }, - { "id": "output-1", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [{}], - "sequence": ["input-1", "output-1"] -} diff --git a/packages/breadboard/tests/data/simple-loop-2.json b/packages/breadboard/tests/data/simple-loop-2.json deleted file mode 100644 index 5fc6b6a3473..00000000000 --- a/packages/breadboard/tests/data/simple-loop-2.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "description": "This tests for the fun ordering case of `simple-loop.json` that Paul Kinlan discovered in his adventures. Thank you, Paul. Edge queueing was implemented as a result of this discovery.", - "edges": [ - { - "from": "input", - "out": "list", - "to": "extract", - "in": "list" - }, - { - "from": "extract", - "out": "list", - "to": "extract", - "in": "list" - }, - { - "from": "extract", - "out": "text", - "to": "output", - "in": "text" - } - ], - "nodes": [ - { "id": "input", "type": "input" }, - { "id": "output", "type": "output" }, - { "id": "extract", "type": "extract" } - ], - "inputs": { "list": ["a", "b", "c", "d", "e", "f", "g"] }, - "outputs": [ - { "text": "a" }, - { "text": "b" }, - { "text": "c" }, - { "text": "d" }, - { "text": "e" }, - { "text": "f" }, - { "text": "g" } - ], - "sequence": [ - "input", - "extract", - "extract", - "output", - "extract", - "output", - "extract", - "output", - "extract", - "output", - "extract", - "output", - "extract", - "output", - "output" - ] -} diff --git a/packages/breadboard/tests/data/simple-loop.json b/packages/breadboard/tests/data/simple-loop.json deleted file mode 100644 index dd917dadce7..00000000000 --- a/packages/breadboard/tests/data/simple-loop.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "edges": [ - { - "from": "input", - "out": "list", - "to": "extract", - "in": "list" - }, - { - "from": "extract", - "out": "text", - "to": "output", - "in": "text" - }, - { - "from": "extract", - "out": "list", - "to": "extract", - "in": "list" - } - ], - "nodes": [ - { "id": "input", "type": "input" }, - { "id": "output", "type": "output" }, - { "id": "extract", "type": "extract" } - ], - "inputs": { "list": ["a", "b", "c", "d", "e", "f", "g"] }, - "outputs": [ - { "text": "a" }, - { "text": "b" }, - { "text": "c" }, - { "text": "d" }, - { "text": "e" }, - { "text": "f" }, - { "text": "g" } - ], - "sequence": [ - "input", - "extract", - "output", - "extract", - "output", - "extract", - "output", - "extract", - "output", - "extract", - "output", - "extract", - "output", - "extract", - "output" - ] -} diff --git a/packages/breadboard/tests/data/simple-start-tag.json b/packages/breadboard/tests/data/simple-start-tag.json deleted file mode 100644 index 10be2dd284a..00000000000 --- a/packages/breadboard/tests/data/simple-start-tag.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "edges": [ - { - "from": "node-b", - "out": "text", - "to": "node-c", - "in": "data" - }, - { - "from": "node-a", - "out": "text", - "to": "node-d", - "in": "data" - } - ], - "nodes": [ - { "id": "node-a", "type": "input" }, - { - "id": "node-b", - "type": "input", - "metadata": { - "tags": ["start"] - } - }, - { "id": "node-c", "type": "output" }, - { "id": "node-d", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [{ "data": "foo" }], - "sequence": ["node-b", "node-c"] -} diff --git a/packages/breadboard/tests/data/simple.json b/packages/breadboard/tests/data/simple.json deleted file mode 100644 index abc899c0971..00000000000 --- a/packages/breadboard/tests/data/simple.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "edges": [ - { - "from": "input-1", - "out": "text", - "to": "output-1", - "in": "text" - } - ], - "nodes": [ - { "id": "input-1", "type": "input" }, - { "id": "output-1", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [{ "text": "foo" }], - "sequence": ["input-1", "output-1"] -} diff --git a/packages/breadboard/tests/data/specified-start-tag.json b/packages/breadboard/tests/data/specified-start-tag.json deleted file mode 100644 index 6269901769a..00000000000 --- a/packages/breadboard/tests/data/specified-start-tag.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "edges": [ - { - "from": "node-b", - "out": "text", - "to": "node-c", - "in": "data" - }, - { - "from": "node-a", - "out": "text", - "to": "node-d", - "in": "data" - } - ], - "nodes": [ - { "id": "node-a", "type": "input" }, - { - "id": "node-b", - "type": "input", - "metadata": { - "tags": [ - { - "type": "start" - } - ] - } - }, - { "id": "node-c", "type": "output" }, - { "id": "node-d", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [{ "data": "foo" }], - "sequence": ["node-b", "node-c"] -} diff --git a/packages/breadboard/tests/data/start-tag-in-the-middle.json b/packages/breadboard/tests/data/start-tag-in-the-middle.json deleted file mode 100644 index 5d425141f03..00000000000 --- a/packages/breadboard/tests/data/start-tag-in-the-middle.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "edges": [ - { - "from": "node-a", - "out": "text", - "to": "node-b", - "in": "text" - }, - { - "from": "node-b", - "out": "text", - "to": "node-c", - "in": "text" - } - ], - "nodes": [ - { "id": "node-a", "type": "input" }, - { - "id": "node-b", - "type": "make", - "metadata": { - "tags": [ - { - "type": "start" - } - ] - } - }, - { "id": "node-c", "type": "output" } - ], - "outputs": [{ "text": "Hello, world!" }], - "sequence": ["node-b", "node-c"] -} diff --git a/packages/breadboard/tests/data/two-entries.json b/packages/breadboard/tests/data/two-entries.json deleted file mode 100644 index ed3aefb4096..00000000000 --- a/packages/breadboard/tests/data/two-entries.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "edges": [ - { - "from": "node-a", - "out": "text", - "to": "node-c", - "in": "text" - }, - { - "from": "node-b", - "out": "text", - "to": "node-c", - "in": "data" - } - ], - "nodes": [ - { "id": "node-a", "type": "input" }, - { "id": "node-b", "type": "input" }, - { "id": "node-c", "type": "output" } - ], - "inputs": { "text": "foo" }, - "outputs": [{ "text": "foo", "data": "foo" }], - "sequence": ["node-a", "node-b", "node-c"] -} diff --git a/packages/breadboard/tests/editor/blank.ts b/packages/breadboard/tests/editor/blank.ts deleted file mode 100644 index f226553e569..00000000000 --- a/packages/breadboard/tests/editor/blank.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { blank, inspect } from "../../src/index.js"; - -test("importBlank creates a nice blank board", async (t) => { - const b = blank(); - t.truthy(b); - - // Let's inspect it! - - const inspectable = inspect(b); - - const input = inspectable.nodeById("input"); - t.truthy(input); - - const outgoing = input?.outgoing(); - t.is(outgoing?.length, 1); - - const wire = outgoing?.[0]; - const output = wire?.to; - t.truthy(output); - - t.is(output?.title(), "output"); -}); diff --git a/packages/breadboard/tests/editor/configuration.ts b/packages/breadboard/tests/editor/configuration.ts deleted file mode 100644 index 2c336d355e3..00000000000 --- a/packages/breadboard/tests/editor/configuration.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { testEditGraph } from "./graph.js"; - -test("editGraph correctly edits node configuration", async (t) => { - const graph = testEditGraph(); - const old = graph.inspect().nodeById("node0")?.descriptor?.configuration; - - t.deepEqual(old, undefined); - - const result = await graph.edit( - [ - { - type: "changeconfiguration", - id: "node0", - configuration: { title: "hello " }, - }, - ], - "test" - ); - - t.is(result.success, true); - t.deepEqual(graph.inspect().nodeById("node0")?.descriptor?.configuration, { - title: "hello ", - }); - - const changeResult = await graph.edit( - [ - { - type: "changeconfiguration", - id: "node0", - configuration: { description: "world" }, - }, - ], - "test" - ); - - t.is(changeResult.success, true); - t.deepEqual(graph.inspect().nodeById("node0")?.descriptor?.configuration, { - title: "hello ", - description: "world", - }); - - const resetResult = await graph.edit( - [ - { - type: "changeconfiguration", - id: "node0", - configuration: { title: "goodbye" }, - reset: true, - }, - ], - "test" - ); - t.is(resetResult.success, true); - t.deepEqual(graph.inspect().nodeById("node0")?.descriptor?.configuration, { - title: "goodbye", - }); -}); diff --git a/packages/breadboard/tests/editor/graph.ts b/packages/breadboard/tests/editor/graph.ts deleted file mode 100644 index a8fecda0819..00000000000 --- a/packages/breadboard/tests/editor/graph.ts +++ /dev/null @@ -1,553 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { editGraph } from "../../src/editor/index.js"; -import { NodeHandler } from "../../src/types.js"; - -export const testEditGraph = () => { - return editGraph( - structuredClone({ - nodes: [ - { - id: "node0", - type: "foo", - }, - { - id: "node2", - type: "bar", - }, - ], - edges: [{ from: "node0", out: "out", to: "node0", in: "in" }], - }), - { - kits: [ - { - url: "", - handlers: { - foo: { - invoke: async () => {}, - describe: async () => { - return { - inputSchema: { - additionalProperties: false, - properties: { - in: { type: "string" }, - }, - }, - outputSchema: { - additionalProperties: false, - properties: { - out: { type: "string" }, - }, - }, - }; - }, - } as NodeHandler, - bar: { - invoke: async () => {}, - describe: async () => { - return { - inputSchema: {}, - outputSchema: { - additionalProperties: false, - properties: { - out: { type: "string" }, - }, - }, - }; - }, - } as NodeHandler, - }, - }, - ], - } - ); -}; - -test("editor API successfully tests for node addition", async (t) => { - const graph = testEditGraph(); - - { - const result = await graph.edit( - [ - { - type: "addnode", - node: { - id: "node1", - type: "foo", - }, - }, - ], - "add node", - true - ); - - t.true(result.success); - } - { - const result = await graph.edit( - [ - { - type: "addnode", - node: { - id: "node0", - type: "foo", - }, - }, - ], - "add node", - true - ); - - t.false(result.success); - } - { - const result = await graph.edit( - [ - { - type: "addnode", - node: { - id: "node1", - type: "unknown type", - }, - }, - ], - "add node", - true - ); - - t.false(result.success); - } -}); - -test("editor API successfully adds a node", async (t) => { - const graph = testEditGraph(); - - const result = await graph.edit( - [ - { - type: "addnode", - node: { - id: "node1", - type: "foo", - }, - }, - ], - "add node" - ); - - t.true(result.success); - - const raw = graph.raw(); - t.deepEqual( - raw.nodes.map((n) => n.id), - ["node0", "node2", "node1"] - ); -}); - -test("editor API successfully tests for node removal", async (t) => { - const graph = testEditGraph(); - - { - const result = await graph.edit( - [{ type: "removenode", id: "node0" }], - "remove node", - true - ); - - t.true(result.success); - } - { - const result = await graph.edit( - [{ type: "removenode", id: "node1" }], - "remove node", - true - ); - - t.false(result.success); - } -}); - -test("editor API successfully removes a node", async (t) => { - const graph = testEditGraph(); - { - const result = await graph.edit( - [{ type: "removenode", id: "node0" }], - "remove node" - ); - - t.true(result.success); - - const raw = graph.raw(); - t.deepEqual( - raw.nodes.map((n) => n.id), - ["node2"] - ); - t.deepEqual( - raw.edges.map((e) => [e.from, e.to]), - [] - ); - } - - { - const result = await graph.edit( - [{ type: "addnode", node: { id: "node0", type: "foo" } }], - "add node", - true - ); - t.true(result.success); - } -}); - -test("editor API successfully tests for edge addition", async (t) => { - const graph = testEditGraph(); - - { - const result = await graph.edit( - [ - { - type: "addedge", - edge: { from: "node0", out: "out", to: "node2", in: "in" }, - }, - ], - "add edge", - true - ); - - t.true(result.success); - } - { - const result = await graph.edit( - [ - { - type: "addedge", - edge: { from: "node0", out: "out", to: "node0", in: "in" }, - }, - ], - "add edge", - true - ); - - t.false(result.success); - } - { - const result = await graph.edit( - [ - { - type: "addedge", - edge: { from: "node0", out: "out", to: "node0", in: "baz" }, - }, - ], - "add edge", - true - ); - - t.false(result.success); - } - { - const result = await graph.edit( - [ - { - type: "addedge", - edge: { from: "unknown node", out: "out", to: "node2", in: "in" }, - }, - ], - "add edge", - true - ); - - t.false(result.success); - } - { - const result = await graph.edit( - [ - { - type: "addedge", - edge: { from: "node0", out: "out", to: "unknown node", in: "in" }, - }, - ], - "add edge", - true - ); - - t.false(result.success); - } -}); - -test("editor API successfully adds an edge", async (t) => { - const graph = testEditGraph(); - - { - const result = await graph.edit( - [ - { - type: "addedge", - edge: { from: "node0", out: "out", to: "node2", in: "in" }, - }, - ], - "add edge" - ); - - t.true(result.success); - - const raw = graph.raw(); - t.deepEqual( - raw.edges.map((e) => [e.from, e.to]), - [ - ["node0", "node0"], - ["node0", "node2"], - ] - ); - } - { - const result = await graph.edit( - [ - { - type: "addedge", - edge: { from: "node0", out: "out", to: "node2", in: "in" }, - }, - ], - "add edge", - true - ); - - t.false(result.success); - } -}); - -test("editor API successfully tests for edge removal", async (t) => { - const graph = testEditGraph(); - - { - const result = await graph.edit( - [ - { - type: "removeedge", - edge: { from: "node0", out: "out", to: "node0", in: "in" }, - }, - ], - "remove edge", - true - ); - - t.true(result.success); - } - { - const result = await graph.edit( - [ - { - type: "removeedge", - edge: { from: "node0", out: "out", to: "node0", in: "baz" }, - }, - ], - "remove edge", - true - ); - - t.false(result.success); - } - { - const result = await graph.edit( - [ - { - type: "removeedge", - edge: { from: "unknown node", out: "out", to: "node0", in: "in" }, - }, - ], - "remove edge", - true - ); - - t.false(result.success); - } - { - const result = await graph.edit( - [ - { - type: "removeedge", - edge: { - from: "node0", - out: "out", - to: "unknown node", - in: "in", - }, - }, - ], - "test", - true - ); - - t.false(result.success); - } -}); - -test("editor API successfully removes an edge", async (t) => { - const graph = testEditGraph(); - - { - const result = await graph.edit( - [ - { - type: "removeedge", - edge: { from: "node0", out: "out", to: "node0", in: "in" }, - }, - ], - "test" - ); - - t.true(result.success); - - const raw = graph.raw(); - t.deepEqual( - raw.edges.map((e) => [e.from, e.to]), - [] - ); - } - { - const result = await graph.edit( - [ - { - type: "removeedge", - edge: { from: "node0", out: "out", to: "node0", in: "in" }, - }, - ], - "test", - true - ); - - t.false(result.success); - } -}); - -test("editor API allows adding built-in nodes", async (t) => { - const graph = testEditGraph(); - - { - const result = await graph.edit( - [ - { - type: "addnode", - node: { - id: "node1", - type: "input", - }, - }, - ], - "test" - ); - - t.true(result.success); - - const raw = graph.raw(); - t.deepEqual( - raw.nodes.map((n) => n.id), - ["node0", "node2", "node1"] - ); - } - - { - const result = await graph.edit( - [ - { - type: "addnode", - node: { id: "node3", type: "output" }, - }, - ], - "test" - ); - - t.true(result.success); - - const raw = graph.raw(); - t.deepEqual( - raw.nodes.map((n) => n.id), - ["node0", "node2", "node1", "node3"] - ); - } -}); - -test("editor API allows changing edge", async (t) => { - const graph = testEditGraph(); - - const before = graph.inspect().edges()[0]; - - const result = await graph.edit( - [ - { - type: "changeedge", - from: { from: "node0", out: "out", to: "node0", in: "in" }, - to: { from: "node0", out: "out", to: "node2", in: "in" }, - }, - ], - "test" - ); - - t.true(result.success); - - const raw = graph.raw(); - t.deepEqual( - raw.edges.map((e) => [e.from, e.to]), - [["node0", "node2"]] - ); - - const after = graph.inspect().edges()[0]; - t.assert(before === after); -}); - -test("editor API does not allow connecting a specific output port to a star port", async (t) => { - const graph = testEditGraph(); - - const edgeSpec = { from: "node0", out: "out", to: "node2", in: "*" }; - const result = await graph.edit( - [{ type: "addedge", edge: edgeSpec }], - "test", - true - ); - t.false(result.success); -}); - -test("editor API correctly works with no subgraphs", (t) => { - const graph = testEditGraph(); - - const raw = graph.raw(); - t.falsy(raw.graphs); -}); - -test("editor API correctly allows adding, removing, replacing subgraphs", (t) => { - const graph = testEditGraph(); - const subgraph = testEditGraph().raw(); - - t.assert(graph.addGraph("foo", subgraph) !== null); - - t.truthy(graph.raw().graphs); - - t.is(graph.version(), 1); - - t.assert(graph.addGraph("foo", subgraph) === null); - - t.true(graph.removeGraph("foo").success); - t.false(graph.removeGraph("foo").success); - - t.falsy(graph.raw().graphs); - - t.is(graph.version(), 2); - - t.assert(graph.replaceGraph("foo", subgraph) === null); - - t.is(graph.version(), 2); - - t.assert(graph.addGraph("foo", subgraph) !== null); - - t.is(graph.version(), 3); - - t.assert(graph.replaceGraph("foo", subgraph) !== null); - - t.is(graph.version(), 4); - - t.truthy(graph.raw().graphs); -}); diff --git a/packages/breadboard/tests/editor/history.ts b/packages/breadboard/tests/editor/history.ts deleted file mode 100644 index 61b67f01ea5..00000000000 --- a/packages/breadboard/tests/editor/history.ts +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { EditHistoryManager } from "../../src/editor/history.js"; -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; - -test("EditHistoryManager correctly adds new items", (t) => { - const mockGraph1 = { m: "1" } as unknown as GraphDescriptor; - const mockGraph2 = { m: "2" } as unknown as GraphDescriptor; - const history = new EditHistoryManager(); - t.assert(history.current() === null); - history.add(mockGraph1, "test"); - t.deepEqual(history.current(), mockGraph1); - t.assert(history.history.length === 1); - history.add(mockGraph2, "test"); - t.deepEqual(history.current(), mockGraph2); - t.assert(history.history.length === 2); -}); - -test("EditHistoryManager correctly goes back", (t) => { - const mockGraph1 = { m: "1" } as unknown as GraphDescriptor; - const mockGraph2 = { m: "2" } as unknown as GraphDescriptor; - const mockGraph3 = { m: "3" } as unknown as GraphDescriptor; - const history = new EditHistoryManager(); - history.add(mockGraph1, "test"); - history.add(mockGraph2, "test"); - history.add(mockGraph3, "test"); - t.deepEqual(history.back(), mockGraph2); - t.deepEqual(history.back(), mockGraph1); - t.deepEqual(history.back(), mockGraph1); -}); - -test("EditHistoryManager correctly goes forth", (t) => { - const mockGraph1 = { m: "1" } as unknown as GraphDescriptor; - const mockGraph2 = { m: "2" } as unknown as GraphDescriptor; - const mockGraph3 = { m: "3" } as unknown as GraphDescriptor; - const history = new EditHistoryManager(); - history.add(mockGraph1, "test"); - history.add(mockGraph2, "test"); - history.add(mockGraph3, "test"); - t.deepEqual(history.back(), mockGraph2); - t.deepEqual(history.back(), mockGraph1); - t.deepEqual(history.back(), mockGraph1); - t.deepEqual(history.forth(), mockGraph2); - t.deepEqual(history.forth(), mockGraph3); - t.deepEqual(history.forth(), mockGraph3); -}); - -test("EditHistoryManager correctly combines add, back, and forth", (t) => { - const mockGraph1 = { m: "1" } as unknown as GraphDescriptor; - const mockGraph2 = { m: "2" } as unknown as GraphDescriptor; - const mockGraph3 = { m: "3" } as unknown as GraphDescriptor; - const mockGraph4 = { m: "4" } as unknown as GraphDescriptor; - const history = new EditHistoryManager(); - history.add(mockGraph1, "test"); - history.add(mockGraph2, "test"); - t.deepEqual(history.back(), mockGraph1); - history.add(mockGraph3, "test"); - t.deepEqual(history.current(), mockGraph3); - t.deepEqual(history.forth(), mockGraph3); - t.deepEqual(history.back(), mockGraph1); - t.deepEqual(history.forth(), mockGraph3); - history.add(mockGraph4, "test"); - t.deepEqual(history.current(), mockGraph4); - t.deepEqual(history.back(), mockGraph3); - t.deepEqual(history.back(), mockGraph1); -}); - -test("EditHistoryManager knows how to pause and resume", (t) => { - const mockGraph1 = { m: "1" } as unknown as GraphDescriptor; - const mockGraph2 = { m: "2" } as unknown as GraphDescriptor; - const mockGraph3 = { m: "3" } as unknown as GraphDescriptor; - const history = new EditHistoryManager(); - history.add(mockGraph1, "test"); - history.add(mockGraph2, "test"); - history.add(mockGraph3, "test"); - t.deepEqual(history.back(), mockGraph2); - history.pause("test", mockGraph2, 1); - t.assert(history.paused()); - t.deepEqual(history.back(), null); - t.deepEqual(history.forth(), null); - history.resume(mockGraph3, 2); - t.assert(!history.paused()); - t.deepEqual(history.current(), mockGraph3); - t.deepEqual(history.back(), mockGraph2); - t.deepEqual(history.back(), mockGraph1); -}); - -test("EditHistoryManager correctly recognizes different pause labels", (t) => { - const mockGraph1 = { m: "1" } as unknown as GraphDescriptor; - const mockGraph2 = { m: "2" } as unknown as GraphDescriptor; - const mockGraph3 = { m: "3" } as unknown as GraphDescriptor; - const mockGraph4 = { m: "4" } as unknown as GraphDescriptor; - const history = new EditHistoryManager(); - history.add(mockGraph1, "test"); - history.add(mockGraph2, "test"); - history.add(mockGraph3, "test"); - t.deepEqual(history.back(), mockGraph2); - history.pause("test", mockGraph2, 1); - t.assert(history.paused()); - t.deepEqual(history.back(), null); - t.deepEqual(history.forth(), null); - history.pause("test2", mockGraph3, 2); - t.assert(history.paused()); - t.deepEqual(history.back(), null); - t.deepEqual(history.forth(), null); - history.resume(mockGraph4, 3); - t.assert(!history.paused()); - t.deepEqual(history.current(), mockGraph4); - t.deepEqual(history.back(), mockGraph3); - t.deepEqual(history.back(), mockGraph2); -}); diff --git a/packages/breadboard/tests/editor/metadata.ts b/packages/breadboard/tests/editor/metadata.ts deleted file mode 100644 index 995815917fb..00000000000 --- a/packages/breadboard/tests/editor/metadata.ts +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { editGraph } from "../../src/editor/index.js"; -import { NodeMetadata } from "@google-labs/breadboard-schema/graph.js"; - -const testEditGraph = () => { - return editGraph( - structuredClone({ - nodes: [ - { - id: "node0", - type: "foo", - }, - { - id: "node2", - type: "bar", - }, - ], - edges: [{ from: "node0", out: "out", to: "node0", in: "in" }], - }), - {} - ); -}; - -test("editGraph correctly edits node metadata", async (t) => { - const graph = testEditGraph(); - const metadata = graph.inspect().nodeById("node0")?.descriptor?.metadata; - t.is(metadata, undefined); - - const result = await graph.edit( - [{ type: "changemetadata", id: "node0", metadata: {} }], - "test", - true - ); - t.is(result.success, true); - - const newMetadata = { title: "bar" }; - const changeResult = await graph.edit( - [{ type: "changemetadata", id: "node0", metadata: newMetadata }], - "test" - ); - t.is(changeResult.success, true); - t.is(graph.version(), 1); - - const changedMetadata = graph.inspect().nodeById("node0") - ?.descriptor?.metadata; - t.deepEqual(changedMetadata, newMetadata); - - const invalidResult = await graph.edit( - [ - { - type: "changemetadata", - id: "nonexistentNode", - metadata: { title: "baz" }, - }, - ], - "test" - ); - t.is(invalidResult.success, false); - t.is(graph.version(), 1); -}); - -test("editGraph correctly edits visual node metadata", async (t) => { - const graph = testEditGraph(); - const metadata = graph.inspect().nodeById("node0")?.descriptor?.metadata; - t.is(metadata, undefined); - - const result = await graph.edit( - [{ type: "changemetadata", id: "node0", metadata: {} }], - "test", - true - ); - t.is(result.success, true); - - const newMetadata = { visual: { icon: "cool" } } satisfies NodeMetadata; - graph.addEventListener("graphchange", (evt) => { - t.true(evt.visualOnly); - }); - const changeResult = await graph.edit( - [{ type: "changemetadata", id: "node0", metadata: newMetadata }], - "test" - ); - t.is(changeResult.success, true); - t.is(graph.version(), 1); - - const changedMetadata = graph.inspect().nodeById("node0") - ?.descriptor?.metadata; - t.deepEqual(changedMetadata, newMetadata); - - const invalidResult = await graph.edit( - [ - { - type: "changemetadata", - id: "nonexistentNode", - metadata: { title: "baz" }, - }, - ], - "test" - ); - t.is(invalidResult.success, false); - t.is(graph.version(), 1); -}); - -test("editGraph correctly distinguishes between `reset` and incremental graph metadata changes", async (t) => { - const graph = testEditGraph(); - - const result = await graph.edit( - [ - { type: "changemetadata", id: "node0", metadata: { title: "hello" } }, - { - type: "changemetadata", - id: "node0", - metadata: { visual: { x: 8, y: 10 } }, - }, - ], - "test" - ); - t.is(result.success, true); - const changedMetadata = graph.inspect().nodeById("node0") - ?.descriptor?.metadata; - t.deepEqual(changedMetadata, { title: "hello", visual: { x: 8, y: 10 } }); -}); diff --git a/packages/breadboard/tests/editor/multi.ts b/packages/breadboard/tests/editor/multi.ts deleted file mode 100644 index 963733a6256..00000000000 --- a/packages/breadboard/tests/editor/multi.ts +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { testEditGraph } from "./graph.js"; - -test("Multi-edit returns a last failed edit's error message", async (t) => { - const graph = testEditGraph(); - const result = await graph.edit( - [{ type: "addnode", node: { id: "node0", type: "foo" } }], - "test", - true - ); - - if (result.success) { - t.fail(); - return; - } - t.true(result.log.length === 1); - const singleEdit = result.log[0].result; - if (singleEdit.success) { - t.fail(); - return; - } - t.assert(result.error === singleEdit.error); -}); - -test("Multi-edit can do multiple successful edits", async (t) => { - { - const graph = testEditGraph(); - let graphChangeRejectDispatched = false; - let graphChangeDispatched = false; - graph.addEventListener("graphchange", () => { - graphChangeDispatched = true; - }); - graph.addEventListener("graphchangereject", () => { - graphChangeRejectDispatched = true; - }); - const oldVersion = graph.version(); - const result = await graph.edit( - [ - { type: "addnode", node: { id: "node-1", type: "foo" } }, - { type: "addnode", node: { id: "node-2", type: "foo" } }, - { type: "addnode", node: { id: "node-3", type: "foo" } }, - ], - "test" - ); - t.true(result.success); - const inspector = graph.inspect(); - t.assert(inspector.nodeById("node-1")); - t.assert(inspector.nodeById("node-2")); - t.assert(inspector.nodeById("node-3")); - t.assert(oldVersion === graph.version() - 1); - t.true(graphChangeDispatched); - t.false(graphChangeRejectDispatched); - } - { - const graph = testEditGraph(); - let graphChangeRejectDispatched = false; - let graphChangeDispatched = false; - graph.addEventListener("graphchange", () => { - graphChangeDispatched = true; - }); - graph.addEventListener("graphchangereject", () => { - graphChangeRejectDispatched = true; - }); - const oldVersion = graph.version(); - const result = await graph.edit( - [ - { type: "addnode", node: { id: "node-1", type: "foo" } }, - { type: "addnode", node: { id: "node-2", type: "foo" } }, - { type: "addnode", node: { id: "node-3", type: "foo" } }, - ], - "test", - true - ); - t.true(result.success); - const inspector = graph.inspect(); - t.assert(!inspector.nodeById("node-1")); - t.assert(!inspector.nodeById("node-2")); - t.assert(!inspector.nodeById("node-3")); - t.assert(oldVersion === graph.version()); - t.false(graphChangeDispatched); - t.false(graphChangeRejectDispatched); - } -}); - -test("Multi-edit gracefully fails", async (t) => { - { - const graph = testEditGraph(); - let graphChangeRejectDispatched = false; - let graphChangeDispatched = false; - graph.addEventListener("graphchange", () => { - graphChangeDispatched = true; - }); - graph.addEventListener("graphchangereject", () => { - graphChangeRejectDispatched = true; - }); - const oldVersion = graph.version(); - const result = await graph.edit( - [ - { type: "addnode", node: { id: "node-1", type: "foo" } }, - { type: "addnode", node: { id: "node0", type: "foo" } }, - { type: "addnode", node: { id: "node-3", type: "foo" } }, - ], - "test" - ); - if (result.success) { - t.fail(); - return; - } - const failedEdit = result.log[1]; - t.is(failedEdit.edit, "addnode"); - if (failedEdit.result.success) { - t.fail(); - return; - } - const inspector = graph.inspect(); - t.assert(!inspector.nodeById("node-1")); - t.assert(!inspector.nodeById("node-3")); - t.assert(oldVersion === graph.version()); - t.false(graphChangeDispatched); - t.true(graphChangeRejectDispatched); - } - { - const graph = testEditGraph(); - let graphChangeRejectDispatched = false; - let graphChangeDispatched = false; - graph.addEventListener("graphchange", () => { - graphChangeDispatched = true; - }); - graph.addEventListener("graphchangereject", () => { - graphChangeRejectDispatched = true; - }); - const oldVersion = graph.version(); - const result = await graph.edit( - [ - { type: "addnode", node: { id: "node-1", type: "foo" } }, - { type: "addnode", node: { id: "node-1", type: "foo" } }, - { type: "addnode", node: { id: "node-3", type: "foo" } }, - ], - "test" - ); - if (result.success) { - t.fail(); - return; - } - const failedEdit = result.log[1]; - t.is(failedEdit.edit, "addnode"); - if (failedEdit.result.success) { - t.fail(); - return; - } - const inspector = graph.inspect(); - t.assert(!inspector.nodeById("node-1")); - t.assert(!inspector.nodeById("node-3")); - t.assert(oldVersion === graph.version()); - t.false(graphChangeDispatched); - t.true(graphChangeRejectDispatched); - } -}); diff --git a/packages/breadboard/tests/helpers/_test-kit.ts b/packages/breadboard/tests/helpers/_test-kit.ts deleted file mode 100644 index 618744af5c5..00000000000 --- a/packages/breadboard/tests/helpers/_test-kit.ts +++ /dev/null @@ -1,264 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { KitBuilder } from "../../src/kits/index.js"; -import { StreamCapability } from "../../src/stream.js"; -import { - BreadboardCapability, - GraphDescriptor, - GraphDescriptorBoardCapability, - InputValues, - NodeDescriberResult, - NodeHandlerContext, - Schema, -} from "../../src/types.js"; - -type IncludeInputValues = InputValues & { - graph?: GraphDescriptor; -}; - -type InvokeInputValues = InputValues & { - board?: BreadboardCapability; - path?: string; -}; -/** - * This is a Kit designed specifically for use in the testing harness. - */ -export const TestKit = new KitBuilder({ - url: ".", -}).build({ - /** - * Just a no-op node. - * @param inputs Any inputs to the node. - * @returns Sme inputs - */ - noop: async (inputs) => inputs, - /** - * Just a no-op node, called "test, for when need two noop nodes with - * different names. This is useful for testing that the name is stripped - * from the regular "noop". - * @param inputs Any inputs to the node. - * @returns Sme inputs - */ - test: async (inputs) => inputs, - /** - * This is a primitive implementation of the `include` node in Core Kit, - * just enough for testing. - */ - include: async (inputs: InputValues, context: NodeHandlerContext) => { - const { graph } = inputs as IncludeInputValues; - if (!graph) { - throw new Error("Must provide a graph to include"); - } - return await invokeGraph(graph, inputs, context); - }, - /** - * This is a primitive implementation of the `invoke` node in Core Kit, - * just enough for testing. - */ - invoke: { - invoke: async (inputs: InvokeInputValues, context: NodeHandlerContext) => { - const { $board, ...args } = inputs; - const base = context.base || new URL(import.meta.url); - - if ($board) { - const board = - ($board as BreadboardCapability).kind === "board" - ? await getGraphDescriptor($board as BreadboardCapability, context) - : typeof $board === "string" - ? await context.loader?.load($board, { - base, - outerGraph: context.outerGraph, - }) - : undefined; - - if (!board) throw new Error("Must provide valid $board to invoke"); - - return await invokeGraph(board, args, context); - } else { - const { board, path, ...args } = inputs; - - const runnableBoard = board - ? await getGraphDescriptor(board, context) - : path - ? await context.loader?.load(path, { - base, - outerGraph: context.outerGraph, - }) - : undefined; - - if (!runnableBoard) - throw new Error("Must provide valid board to invoke"); - - return await invokeGraph(runnableBoard, args, context); - } - }, - describe: async (inputs?: InputValues): Promise => { - // Bare subset of describe() for invoke: Find the first input and output - // nodes of inline supplied graphs (no loading), and use their schemas. - let graph: GraphDescriptor | undefined = undefined; - if ( - inputs?.$board && - (inputs?.$board as BreadboardCapability).kind === "board" - ) { - graph = (inputs?.$board as GraphDescriptorBoardCapability).board; - } else if ( - inputs?.board && - (inputs.board as BreadboardCapability).kind === "board" - ) { - graph = (inputs.board as GraphDescriptorBoardCapability).board; - } else if (inputs?.graph) { - graph = inputs.graph as GraphDescriptor; - } - - const inputSchema = - (graph?.nodes.find((n) => n.type === "input" && n.configuration?.schema) - ?.configuration?.schema as Schema) ?? {}; - const outputSchema = - (graph?.nodes.find( - (n) => n.type === "output" && n.configuration?.schema - )?.configuration?.schema as Schema) ?? {}; - - return { inputSchema, outputSchema }; - }, - }, - /** - * Reverses provided string inputs. Will crash if provided non-string inputs. - * @param inputs InputValues - */ - reverser: { - invoke: async (inputs) => { - return Object.fromEntries( - Object.entries(inputs).map(([key, value]) => [ - key, - (inputs[key] = [...(value as string)].reverse().join("")), - ]) - ); - }, - describe: async ( - inputs?: InputValues, - inputSchema?: Schema - ): Promise => { - const ports = [ - ...Object.keys(inputs ?? {}), - ...Object.keys(inputSchema?.properties ?? {}), - ]; - - const schema = (op: string) => ({ - title: "Reverser", - description: "Reverses the provided string inputs", - type: "object", - properties: Object.fromEntries( - ports.map((port) => [ - port, - { - type: "string", - title: inputSchema?.properties?.[port]?.title ?? port, - description: - op + - (inputSchema?.properties?.[port]?.description ?? - inputSchema?.properties?.[port]?.title ?? - port), - }, - ]) - ), - additionalProperties: Object.entries(inputs ?? {}).length === 0, - }); - - return { - inputSchema: schema("Reverse: "), - outputSchema: schema("Reversed: "), - }; - }, - }, - /** - * Supplies a simple stream output that can be used to test interactions with - * streams. - */ - streamer: async () => { - const words = "Breadboard is a project that helps you make AI boards."; - const stream = new ReadableStream({ - start(controller) { - for (const word of words.split(" ")) { - controller.enqueue(`${word} `); - } - controller.close(); - }, - }); - return { stream: new StreamCapability(stream) }; - }, - /** - * Unsafe JS runner. Needed to test serializing boards that are pure code. - */ - runJavascript: async (inputs) => { - const { code, name, raw, ...rest } = inputs; - const result = eval( - `${code} (async () => { return await ${name}(${JSON.stringify( - rest - )}); })();` - ); - return raw ? result : { result }; - }, -}); - -/** - * This kit is used to test proxying and provides a different behavior than - * the reverser in TestKit. - */ -export const MirrorUniverseKit = new KitBuilder({ - url: "mirror-universe-kit", -}).build({ - /** - * Unlike the reverser in TestKit, it orders letters alphabetically. - * @param inputs InputValues - */ - reverser: async (inputs) => { - return Object.fromEntries( - Object.entries(inputs).map(([key, value]) => [ - key, - (inputs[key] = [...(value as string)].sort().join("")), - ]) - ); - }, -}); - -/** - * Board grammar versions of the above, with types. - */ -import { - addKit, - NewNodeValue, - NewInputValues, - NewOutputValues, - NewNodeFactory as NodeFactory, - invokeGraph, -} from "../../src/index.js"; -import { getGraphDescriptor } from "../../src/capability.js"; - -export const testKit = addKit(TestKit) as unknown as { - noop: NodeFactory; - test: NodeFactory; - reverser: NodeFactory<{ [key: string]: string }, { [key: string]: string }>; - streamer: NodeFactory< - Record, - { stream: ReadableStream } - >; - runJavascript: NodeFactory< - { - code: string; - name: string; - raw: boolean; - [key: string]: NewNodeValue; - }, - { result: unknown; [k: string]: unknown } - >; -}; - -// This will create a kit only when called, so we can test scoping. -export const makeMirrorUniverseKit = () => - addKit(MirrorUniverseKit) as unknown as { - reverser: NodeFactory<{ [key: string]: string }, { [key: string]: string }>; - }; diff --git a/packages/breadboard/tests/helpers/_test-transport.ts b/packages/breadboard/tests/helpers/_test-transport.ts deleted file mode 100644 index 190e9789c85..00000000000 --- a/packages/breadboard/tests/helpers/_test-transport.ts +++ /dev/null @@ -1,161 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { ClientTransport, ServerTransport } from "../../src/remote/types.js"; -import { PatchedReadableStream } from "../../src/stream.js"; -import { ServerRequest, ServerResponse } from "../../src/remote/http.js"; -import { TransformStream } from "stream/web"; - -export class IdentityTransport - implements - ServerTransport, - ClientTransport -{ - #requestPipe = new TransformStream(); - #responsePipe = new TransformStream(); - - createClientStream() { - return { - writableRequests: this.#requestPipe.writable, - readableResponses: this.#responsePipe - .readable as PatchedReadableStream, - }; - } - - createServerStream() { - return { - readableRequests: this.#requestPipe - .readable as PatchedReadableStream, - writableResponses: this.#responsePipe.writable, - }; - } -} - -type MockRequestHandler = ( - request: ServerRequest, - response: ServerResponse -) => void; - -type MockHTTPConnectionOptions = { - breakChunks?: boolean; - combineChunks?: boolean; -}; - -const createChunkMutator = (options: MockHTTPConnectionOptions) => { - const { breakChunks, combineChunks } = options; - if (breakChunks) { - return ( - response: unknown, - writer: WritableStreamDefaultWriter - ) => { - if (typeof response !== "string") - throw new Error("Expected string response."); - const encoder = new TextEncoder(); - // split chunk in two - const chunkSize = Math.floor(response.length / 2); - for (let i = 0; i < response.length; i += chunkSize) { - writer.write(encoder.encode(response.slice(i, i + chunkSize))); - } - }; - } else if (combineChunks) { - const chunkQueue: Uint8Array[] = []; - return ( - response: unknown, - writer: WritableStreamDefaultWriter - ) => { - if (typeof response !== "string") - throw new Error("Expected string response."); - const encoder = new TextEncoder(); - // remember chunks in a queue of 2 - // and push them when the queue is full - chunkQueue.push(encoder.encode(response)); - if (chunkQueue.length < 2) return; - while (chunkQueue.length > 0) { - writer.write(chunkQueue.shift()); - } - }; - } else { - return ( - response: unknown, - writer: WritableStreamDefaultWriter - ) => { - if (typeof response !== "string") - throw new Error("Expected string response."); - writer.write(new TextEncoder().encode(response)); - }; - } -}; - -/** - * Creates a pretend Internet to enable end-to-end testing - * of HTTPClientTransport and HTTPServerTransport. - */ -export class MockHTTPConnection { - #handler?: MockRequestHandler; - #options: MockHTTPConnectionOptions; - - constructor(options: MockHTTPConnectionOptions = {}) { - this.#options = options; - } - - get fetch() { - return async (_: unknown, init?: RequestInit) => { - const pipe = new TransformStream(); - const writer = pipe.writable.getWriter(); - if (!this.#handler) throw new Error("Set request handler first."); - const { body } = init || {}; - const request = { body: JSON.parse(body as string) }; - const chunkMutator = createChunkMutator(this.#options); - const response = { - header() { - return; - }, - write(response: unknown) { - chunkMutator(response, writer); - return true; - }, - async end() { - await writer.close(); - }, - }; - this.#handler(request, response); - - return { - ok: true, - get body() { - return pipe.readable; - }, - } as unknown as globalThis.Response; - }; - } - - onRequest(handler: MockRequestHandler) { - this.#handler = handler; - } -} - -/** - * Creates a pretend Worker to enable end-to-end testing - * of WorkerClientTransport and WorkerServerTransport. - * - * Returns an pair of objects that look like worker and - * worker host (both are Worker instances in TS). - * The objects implement: - * - postMessage - * - addEventListener - * And act as if they are connected to each other. - */ -export const createMockWorkers = () => { - const channel = new MessageChannel(); - const port1 = channel.port1; - const port2 = channel.port2; - port1.start(); - port2.start(); - return { - worker: port1 as unknown as Worker, - host: port2 as unknown as Worker, - }; -}; diff --git a/packages/breadboard/tests/id.ts b/packages/breadboard/tests/id.ts deleted file mode 100644 index fc4c3f72046..00000000000 --- a/packages/breadboard/tests/id.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { IdVendor } from "../src/id.js"; - -test("IdVendor vends unique ids", (t) => { - const vendor = new IdVendor(); - const o1 = {}; - const o2 = {}; - const id1 = vendor.vendId(o1, "test"); - const id2 = vendor.vendId(o1, "test"); - const id3 = vendor.vendId(o2, "test"); - const id4 = vendor.vendId(o2, "test"); - t.not(id1, id2); - t.not(id3, id4); - t.is(id1, id3); - t.is(id2, id4); -}); - -test("IdVendor vends ids with the given prefix", (t) => { - const vendor = new IdVendor(); - const id = vendor.vendId({}, "test"); - t.assert(id.startsWith("test-")); -}); diff --git a/packages/breadboard/tests/inspector/data/gemini-generator-no-schema.json b/packages/breadboard/tests/inspector/data/gemini-generator-no-schema.json deleted file mode 100644 index 2107e86567a..00000000000 --- a/packages/breadboard/tests/inspector/data/gemini-generator-no-schema.json +++ /dev/null @@ -1,225 +0,0 @@ -{ - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output" - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - }, - "required": ["chunk"] - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input" - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or context[-1].role!=\"user\" ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({useStreaming}){const method=useStreaming?\"streamGenerateContent\":\"generateContent\";const sseOption=useStreaming?\"&alt=sse\":\"\";return{method,sseOption}}", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output" - }, - { - "id": "toolCallsOutput", - "type": "output" - } - ], - "graphs": {} -} diff --git a/packages/breadboard/tests/inspector/data/gemini-generator.json b/packages/breadboard/tests/inspector/data/gemini-generator.json deleted file mode 100644 index bb559cbca86..00000000000 --- a/packages/breadboard/tests/inspector/data/gemini-generator.json +++ /dev/null @@ -1,338 +0,0 @@ -{ - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - }, - "required": [ - "chunk" - ] - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": [ - "object", - "string" - ] - } - }, - "required": [ - "chunk" - ] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": [ - "What is the square root of pi?" - ] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "string" - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object" - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": [ - "text" - ] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or context[-1].role!=\"user\" ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({useStreaming}){const method=useStreaming?\"streamGenerateContent\":\"generateContent\";const sseOption=useStreaming?\"&alt=sse\":\"\";return{method,sseOption}}", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": [ - "GEMINI_KEY" - ] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "graphs": {} -} \ No newline at end of file diff --git a/packages/breadboard/tests/inspector/data/loader/ad-writer-2.1.raw.json b/packages/breadboard/tests/inspector/data/loader/ad-writer-2.1.raw.json deleted file mode 100644 index 16f1ce6a0d7..00000000000 --- a/packages/breadboard/tests/inspector/data/loader/ad-writer-2.1.raw.json +++ /dev/null @@ -1,31792 +0,0 @@ -[ - { - "type": "graphstart", - "data": { - "graph": { - "url": "http://localhost:5173/graphs/ad-writer-2.json", - "title": "Ad Writer (variant 2)", - "description": "An example of chain of agents working on writing an ad", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "repeater-8", - "to": "fn-9", - "out": "context", - "in": "context" - }, - { - "from": "repeater-8", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-9", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "structuredWorker-7", - "to": "repeater-8", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-6", - "to": "structuredWorker-7", - "out": "context", - "in": "context" - }, - { - "from": "fn-5", - "to": "structuredWorker-6", - "out": "prompt", - "in": "instruction" - }, - { - "from": "structuredWorker-4", - "to": "structuredWorker-6", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-3", - "to": "fn-5", - "out": "json", - "in": "json" - }, - { - "from": "input-1", - "to": "structuredWorker-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - } - }, - "metadata": { - "visual": { - "x": 1626, - "y": 71 - } - } - }, - { - "id": "repeater-8", - "type": "repeater", - "configuration": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4 - }, - "metadata": { - "title": "Ad refinery", - "visual": { - "x": 1250, - "y": 71 - } - } - }, - { - "id": "fn-9", - "type": "invoke", - "configuration": { - "$board": "#fn-9" - }, - "metadata": { - "title": "JSON Extractor", - "visual": { - "x": 1443, - "y": 177 - } - } - }, - { - "id": "structuredWorker-7", - "type": "structuredWorker", - "configuration": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Editor", - "visual": { - "x": 1045, - "y": 71 - } - } - }, - { - "id": "structuredWorker-6", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - } - }, - "metadata": { - "title": "Customer", - "visual": { - "x": 820, - "y": 71 - } - } - }, - { - "id": "fn-5", - "type": "invoke", - "configuration": { - "$board": "#fn-5" - }, - "metadata": { - "title": "Prompt Extractor", - "visual": { - "x": 595, - "y": 71 - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Writer", - "visual": { - "x": 595, - "y": 263 - } - } - }, - { - "id": "structuredWorker-3", - "type": "structuredWorker", - "configuration": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - } - }, - "metadata": { - "title": "Customer Prompt Maker", - "description": "Conjuring up a persona to represent a customer", - "logLevel": "info", - "visual": { - "x": 331, - "y": 71 - } - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "metadata": { - "visual": { - "x": 77, - "y": 71 - } - } - } - ], - "kits": [], - "graphs": { - "fn-9": { - "edges": [ - { - "from": "fn-9-input", - "to": "fn-9-run", - "out": "*" - }, - { - "from": "fn-9-run", - "to": "fn-9-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-9-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-9-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true - } - }, - { - "id": "fn-9-output", - "type": "output", - "configuration": {} - } - ], - "url": "http://localhost:5173/graphs/ad-writer-2.json#fn-9" - }, - "fn-5": { - "edges": [ - { - "from": "fn-5-input", - "to": "fn-5-run", - "out": "*" - }, - { - "from": "fn-5-run", - "to": "fn-5-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-5-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-5-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true - } - }, - { - "id": "fn-5-output", - "type": "output", - "configuration": {} - } - ], - "url": "http://localhost:5173/graphs/ad-writer-2.json#fn-5" - } - } - }, - "path": [], - "timestamp": 21976.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "metadata": { - "visual": { - "x": 77, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "path": [1], - "timestamp": 21979 - } - }, - { - "type": "input", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "metadata": { - "visual": { - "x": 77, - "y": 71 - } - } - }, - "inputArguments": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "path": [1], - "bubbled": false, - "timestamp": 21986.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "metadata": { - "visual": { - "x": 77, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "outputs": { - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "validatorMetadata": [], - "path": [1], - "timestamp": 30295.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-3", - "type": "structuredWorker", - "configuration": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - } - }, - "metadata": { - "title": "Customer Prompt Maker", - "description": "Conjuring up a persona to represent a customer", - "logLevel": "info", - "visual": { - "x": 331, - "y": 71 - } - } - }, - "inputs": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "path": [2], - "timestamp": 30298.09999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ] - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ] - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ] - } - } - }, - "path": [2], - "timestamp": 30300.399999976158 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [2, 1], - "timestamp": 30300.899999976158 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "validatorMetadata": [], - "path": [2, 1], - "timestamp": 30306 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [2, 2], - "timestamp": 30306.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [2, 2], - "timestamp": 30308.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - } - }, - "path": [2, 3], - "timestamp": 30308.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - } - }, - "outputs": { - "schemish": { - "prompt": "string, the prompt for the bot" - } - }, - "validatorMetadata": [], - "path": [2, 3], - "timestamp": 30309.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "prompt": "string, the prompt for the bot" - } - }, - "path": [2, 9], - "timestamp": 30310.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "prompt": "string, the prompt for the bot" - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "validatorMetadata": [], - "path": [2, 9], - "timestamp": 30312 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "path": [2, 10], - "timestamp": 30312.399999976158 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [2, 10], - "timestamp": 30313.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [2, 10, 1], - "timestamp": 30313.899999976158 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "validatorMetadata": [], - "path": [2, 10, 1], - "timestamp": 30314.399999976158 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "path": [2, 10, 2], - "timestamp": 30314.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [2, 10, 2], - "timestamp": 30324.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [2, 10, 3], - "timestamp": 30325.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [2, 10, 3], - "timestamp": 30325.69999998808 - } - }, - { - "type": "graphend", - "data": { - "path": [2, 10], - "timestamp": 30325.899999976158 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [2, 10], - "timestamp": 30326.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [2, 11], - "timestamp": 30327.5 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [2, 11], - "timestamp": 30329 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [2, 11, 1], - "timestamp": 30329.19999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [2, 11, 1], - "timestamp": 30329.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [2, 11, 2], - "timestamp": 30330 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [2, 11, 2], - "timestamp": 30334.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "path": [2, 11, 3], - "timestamp": 30334.399999976158 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "path": [2, 11, 3], - "timestamp": 30334.69999998808 - } - }, - { - "type": "graphend", - "data": { - "path": [2, 11], - "timestamp": 30335 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [2, 11], - "timestamp": 30335.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [2, 14], - "timestamp": 30335.899999976158 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [2, 14], - "timestamp": 30336.899999976158 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [2, 14, 1], - "timestamp": 30337.5 - } - }, - { - "type": "input", - "data": { - "node": { - "id": "parameters", - "type": "input" - }, - "inputArguments": { - "schema": { - "type": "object", - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - } - } - } - }, - "path": [2, 14, 1], - "bubbled": true, - "timestamp": 30338.19999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [2, 14, 1], - "timestamp": 31415.399999976158 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [2, 14, 2], - "timestamp": 31420 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 31421.399999976158 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [2, 14, 2], - "timestamp": 31423.899999976158 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [2, 14, 3], - "timestamp": 31426.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [2, 14, 3], - "timestamp": 31433.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [2, 14, 4], - "timestamp": 31433.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [2, 14, 4], - "timestamp": 31435 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [2, 14, 5], - "timestamp": 31435.399999976158 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [2, 14, 5], - "timestamp": 31439 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "path": [2, 14, 6], - "timestamp": 31439.399999976158 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [2, 14, 6], - "timestamp": 33804.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [2, 14, 11], - "timestamp": 33806.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```", - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [2, 14, 11], - "timestamp": 33807.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - }, - "path": [2, 14, 13], - "timestamp": 33808.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - }, - "path": [2, 14, 13], - "timestamp": 33808.79999998212 - } - }, - { - "type": "graphend", - "data": { - "path": [2, 14], - "timestamp": 33809 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - }, - "validatorMetadata": [], - "path": [2, 14], - "timestamp": 33809.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "json": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - }, - "path": [2, 16], - "timestamp": 33809.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "json": "```json\n{\n \"prompt\": \"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"\n}\n```" - }, - "outputs": { - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - } - }, - "validatorMetadata": [], - "path": [2, 16], - "timestamp": 33841.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - } - }, - "path": [2, 19], - "timestamp": 33841.79999998212 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [2, 19], - "timestamp": 33842.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [2, 19, 1], - "timestamp": 33843 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - } - }, - "validatorMetadata": [], - "path": [2, 19, 1], - "timestamp": 33843.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - } - }, - "path": [2, 19, 2], - "timestamp": 33843.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"}" - } - } - ] - }, - "validatorMetadata": [], - "path": [2, 19, 2], - "timestamp": 33848.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"}" - } - } - ] - }, - "path": [2, 19, 3], - "timestamp": 33848.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"}" - } - } - ] - }, - "path": [2, 19, 3], - "timestamp": 33848.89999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [2, 19], - "timestamp": 33849.19999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"}" - } - } - ] - }, - "validatorMetadata": [], - "path": [2, 19], - "timestamp": 33849.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"}" - } - } - ] - }, - "path": [2, 20], - "timestamp": 33849.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"}" - } - } - ] - }, - "path": [2, 20], - "timestamp": 33850.29999998212 - } - }, - { - "type": "graphend", - "data": { - "path": [2], - "timestamp": 33850.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-3", - "type": "structuredWorker", - "configuration": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - } - }, - "metadata": { - "title": "Customer Prompt Maker", - "description": "Conjuring up a persona to represent a customer", - "logLevel": "info", - "visual": { - "x": 331, - "y": 71 - } - } - }, - "inputs": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.\"}" - } - } - ] - }, - "validatorMetadata": [], - "path": [2], - "timestamp": 33850.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Writer", - "visual": { - "x": 595, - "y": 263 - } - } - }, - "inputs": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "path": [3], - "timestamp": 33851.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext" - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext" - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count" - } - } - }, - "path": [3], - "timestamp": 33852.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [3, 1], - "timestamp": 33853 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "validatorMetadata": [], - "path": [3, 1], - "timestamp": 33853.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [3, 2], - "timestamp": 33853.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [3, 2], - "timestamp": 33854.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "path": [3, 3], - "timestamp": 33854.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "outputs": { - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "validatorMetadata": [], - "path": [3, 3], - "timestamp": 33854.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "path": [3, 9], - "timestamp": 33855.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [3, 9], - "timestamp": 33856.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [3, 10], - "timestamp": 33856.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [3, 10], - "timestamp": 33857.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [3, 10, 1], - "timestamp": 33857.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [3, 10, 1], - "timestamp": 33858.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [3, 10, 2], - "timestamp": 33858.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [3, 10, 2], - "timestamp": 33862.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [3, 10, 3], - "timestamp": 33862.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [3, 10, 3], - "timestamp": 33863 - } - }, - { - "type": "graphend", - "data": { - "path": [3, 10], - "timestamp": 33863.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [3, 10], - "timestamp": 33863.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [3, 11], - "timestamp": 33863.39999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [3, 11], - "timestamp": 33864.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [3, 11, 1], - "timestamp": 33864.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [3, 11, 1], - "timestamp": 33864.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [3, 11, 2], - "timestamp": 33864.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [3, 11, 2], - "timestamp": 33867 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "path": [3, 11, 3], - "timestamp": 33867.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "path": [3, 11, 3], - "timestamp": 33867.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [3, 11], - "timestamp": 33867.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [3, 11], - "timestamp": 33867.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [3, 14], - "timestamp": 33868.19999998808 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [3, 14], - "timestamp": 33869.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [3, 14, 1], - "timestamp": 33869.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [3, 14, 1], - "timestamp": 33869.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [3, 14, 2], - "timestamp": 33869.79999998212 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 33869.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [3, 14, 2], - "timestamp": 33870.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [3, 14, 3], - "timestamp": 33871.19999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [3, 14, 3], - "timestamp": 33873.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [3, 14, 4], - "timestamp": 33874.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [3, 14, 4], - "timestamp": 33874.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [3, 14, 5], - "timestamp": 33874.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [3, 14, 5], - "timestamp": 33875.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "path": [3, 14, 6], - "timestamp": 33875.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [3, 14, 6], - "timestamp": 40472.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [3, 14, 11], - "timestamp": 40476.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```", - "context": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [3, 14, 11], - "timestamp": 40478.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - }, - "path": [3, 14, 13], - "timestamp": 40479.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - }, - "path": [3, 14, 13], - "timestamp": 40480.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [3, 14], - "timestamp": 40480.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - }, - "validatorMetadata": [], - "path": [3, 14], - "timestamp": 40481.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - }, - "path": [3, 16], - "timestamp": 40482.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Supercharge Dev with Accessible AI\",\n \"Breadboard: The AI Playground for Devs\",\n \"Play, Experiment, Prototype with Ease\",\n \"Unlock AI's Power with Gemini APIs\",\n \"Transform Ideas into Reality with AI\",\n \"Graph Anything with AI Prompts\",\n \"Empowering Devs with AI-Powered Solutions\",\n \"Prototype in Minutes with Breadboard\",\n \"Integrate AI into Your Projects Seamlessly\",\n \"Breadboard: AI Development Simplified\",\n \"Unlock the Potential of AI for Developers\",\n \"Breadboard: Your AI Co-pilot\",\n \"Accelerate App Development with AI Patterns\",\n \"Revolutionize Dev Workflow with Breadboard\",\n \"AI at Your Fingertips with Breadboard\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\n \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\n \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\n \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"\n ]\n }\n}\n```" - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev with Accessible AI", - "Breadboard: The AI Playground for Devs", - "Play, Experiment, Prototype with Ease", - "Unlock AI's Power with Gemini APIs", - "Transform Ideas into Reality with AI", - "Graph Anything with AI Prompts", - "Empowering Devs with AI-Powered Solutions", - "Prototype in Minutes with Breadboard", - "Integrate AI into Your Projects Seamlessly", - "Breadboard: AI Development Simplified", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Accelerate App Development with AI Patterns", - "Revolutionize Dev Workflow with Breadboard", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "validatorMetadata": [], - "path": [3, 16], - "timestamp": 40494.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev with Accessible AI", - "Breadboard: The AI Playground for Devs", - "Play, Experiment, Prototype with Ease", - "Unlock AI's Power with Gemini APIs", - "Transform Ideas into Reality with AI", - "Graph Anything with AI Prompts", - "Empowering Devs with AI-Powered Solutions", - "Prototype in Minutes with Breadboard", - "Integrate AI into Your Projects Seamlessly", - "Breadboard: AI Development Simplified", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Accelerate App Development with AI Patterns", - "Revolutionize Dev Workflow with Breadboard", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "path": [3, 19], - "timestamp": 40496.19999998808 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [3, 19], - "timestamp": 40497.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [3, 19, 1], - "timestamp": 40497.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev with Accessible AI", - "Breadboard: The AI Playground for Devs", - "Play, Experiment, Prototype with Ease", - "Unlock AI's Power with Gemini APIs", - "Transform Ideas into Reality with AI", - "Graph Anything with AI Prompts", - "Empowering Devs with AI-Powered Solutions", - "Prototype in Minutes with Breadboard", - "Integrate AI into Your Projects Seamlessly", - "Breadboard: AI Development Simplified", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Accelerate App Development with AI Patterns", - "Revolutionize Dev Workflow with Breadboard", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "validatorMetadata": [], - "path": [3, 19, 1], - "timestamp": 40498.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev with Accessible AI", - "Breadboard: The AI Playground for Devs", - "Play, Experiment, Prototype with Ease", - "Unlock AI's Power with Gemini APIs", - "Transform Ideas into Reality with AI", - "Graph Anything with AI Prompts", - "Empowering Devs with AI-Powered Solutions", - "Prototype in Minutes with Breadboard", - "Integrate AI into Your Projects Seamlessly", - "Breadboard: AI Development Simplified", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Accelerate App Development with AI Patterns", - "Revolutionize Dev Workflow with Breadboard", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "path": [3, 19, 2], - "timestamp": 40498.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev with Accessible AI", - "Breadboard: The AI Playground for Devs", - "Play, Experiment, Prototype with Ease", - "Unlock AI's Power with Gemini APIs", - "Transform Ideas into Reality with AI", - "Graph Anything with AI Prompts", - "Empowering Devs with AI-Powered Solutions", - "Prototype in Minutes with Breadboard", - "Integrate AI into Your Projects Seamlessly", - "Breadboard: AI Development Simplified", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Accelerate App Development with AI Patterns", - "Revolutionize Dev Workflow with Breadboard", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [3, 19, 2], - "timestamp": 40501.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [3, 19, 3], - "timestamp": 40501.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [3, 19, 3], - "timestamp": 40502.19999998808 - } - }, - { - "type": "graphend", - "data": { - "path": [3, 19], - "timestamp": 40502.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev with Accessible AI", - "Breadboard: The AI Playground for Devs", - "Play, Experiment, Prototype with Ease", - "Unlock AI's Power with Gemini APIs", - "Transform Ideas into Reality with AI", - "Graph Anything with AI Prompts", - "Empowering Devs with AI-Powered Solutions", - "Prototype in Minutes with Breadboard", - "Integrate AI into Your Projects Seamlessly", - "Breadboard: AI Development Simplified", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Accelerate App Development with AI Patterns", - "Revolutionize Dev Workflow with Breadboard", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [3, 19], - "timestamp": 40503.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev with Accessible AI", - "Breadboard: The AI Playground for Devs", - "Play, Experiment, Prototype with Ease", - "Unlock AI's Power with Gemini APIs", - "Transform Ideas into Reality with AI", - "Graph Anything with AI Prompts", - "Empowering Devs with AI-Powered Solutions", - "Prototype in Minutes with Breadboard", - "Integrate AI into Your Projects Seamlessly", - "Breadboard: AI Development Simplified", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Accelerate App Development with AI Patterns", - "Revolutionize Dev Workflow with Breadboard", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [3, 20], - "timestamp": 40503.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev with Accessible AI", - "Breadboard: The AI Playground for Devs", - "Play, Experiment, Prototype with Ease", - "Unlock AI's Power with Gemini APIs", - "Transform Ideas into Reality with AI", - "Graph Anything with AI Prompts", - "Empowering Devs with AI-Powered Solutions", - "Prototype in Minutes with Breadboard", - "Integrate AI into Your Projects Seamlessly", - "Breadboard: AI Development Simplified", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Accelerate App Development with AI Patterns", - "Revolutionize Dev Workflow with Breadboard", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [3, 20], - "timestamp": 40504.59999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [3], - "timestamp": 40504.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Writer", - "visual": { - "x": 595, - "y": 263 - } - } - }, - "inputs": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev with Accessible AI", - "Breadboard: The AI Playground for Devs", - "Play, Experiment, Prototype with Ease", - "Unlock AI's Power with Gemini APIs", - "Transform Ideas into Reality with AI", - "Graph Anything with AI Prompts", - "Empowering Devs with AI-Powered Solutions", - "Prototype in Minutes with Breadboard", - "Integrate AI into Your Projects Seamlessly", - "Breadboard: AI Development Simplified", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Accelerate App Development with AI Patterns", - "Revolutionize Dev Workflow with Breadboard", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [3], - "timestamp": 40505.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-5", - "type": "invoke", - "configuration": { - "$board": "#fn-5" - }, - "metadata": { - "title": "Prompt Extractor", - "visual": { - "x": 595, - "y": 71 - } - } - }, - "inputs": { - "$board": "#fn-5", - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - } - }, - "path": [4], - "timestamp": 40506.39999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "http://localhost:5173/graphs/ad-writer-2.json#fn-5", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "fn-5-input", - "to": "fn-5-run", - "out": "*" - }, - { - "from": "fn-5-run", - "to": "fn-5-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-5-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-5-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true - } - }, - { - "id": "fn-5-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [4], - "timestamp": 40507.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-5-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [4, 1], - "timestamp": 40507.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-5-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - } - }, - "validatorMetadata": [], - "path": [4, 1], - "timestamp": 40508.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-5-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true - } - }, - "inputs": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true, - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - } - }, - "path": [4, 2], - "timestamp": 40508.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-5-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true - } - }, - "inputs": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true, - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - } - }, - "outputs": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - "validatorMetadata": [], - "path": [4, 2], - "timestamp": 40511.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-5-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - "path": [4, 3], - "timestamp": 40511.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-5-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - "path": [4, 3], - "timestamp": 40512.69999998808 - } - }, - { - "type": "graphend", - "data": { - "path": [4], - "timestamp": 40513 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-5", - "type": "invoke", - "configuration": { - "$board": "#fn-5" - }, - "metadata": { - "title": "Prompt Extractor", - "visual": { - "x": 595, - "y": 71 - } - } - }, - "inputs": { - "$board": "#fn-5", - "json": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - } - }, - "outputs": { - "prompt": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - "validatorMetadata": [], - "path": [4], - "timestamp": 40513.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-6", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - } - }, - "metadata": { - "title": "Customer", - "visual": { - "x": 820, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - "path": [5], - "timestamp": 40514.5 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext" - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext" - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count" - } - } - }, - "path": [5], - "timestamp": 40515.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [5, 1], - "timestamp": 40516 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - "validatorMetadata": [], - "path": [5, 1], - "timestamp": 40516.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [5, 2], - "timestamp": 40517.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [5, 2], - "timestamp": 40517.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - } - }, - "path": [5, 3], - "timestamp": 40518 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - } - }, - "outputs": { - "schemish": { - "requirements": [ - { - "requirement": "string, the requirement", - "justification": "string, reasoning behind including this requirement" - } - ] - } - }, - "validatorMetadata": [], - "path": [5, 3], - "timestamp": 40518.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "requirements": [ - { - "requirement": "string, the requirement", - "justification": "string, reasoning behind including this requirement" - } - ] - } - }, - "path": [5, 9], - "timestamp": 40520.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "requirements": [ - { - "requirement": "string, the requirement", - "justification": "string, reasoning behind including this requirement" - } - ] - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "validatorMetadata": [], - "path": [5, 9], - "timestamp": 40521.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "path": [5, 10], - "timestamp": 40521.39999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [5, 10], - "timestamp": 40523.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [5, 10, 1], - "timestamp": 40523.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "validatorMetadata": [], - "path": [5, 10, 1], - "timestamp": 40524 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "path": [5, 10, 2], - "timestamp": 40524.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [5, 10, 2], - "timestamp": 40529.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "path": [5, 10, 3], - "timestamp": 40529.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "path": [5, 10, 3], - "timestamp": 40529.89999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [5, 10], - "timestamp": 40530.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [5, 10], - "timestamp": 40530.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [5, 11], - "timestamp": 40530.59999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [5, 11], - "timestamp": 40531.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [5, 11, 1], - "timestamp": 40531.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [5, 11, 1], - "timestamp": 40531.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [5, 11, 2], - "timestamp": 40532.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [5, 11, 2], - "timestamp": 40534.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [5, 11, 3], - "timestamp": 40534.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [5, 11, 3], - "timestamp": 40534.79999998212 - } - }, - { - "type": "graphend", - "data": { - "path": [5, 11], - "timestamp": 40535 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [5, 11], - "timestamp": 40535.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "path": [5, 14], - "timestamp": 40535.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [5, 14], - "timestamp": 40536.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [5, 14, 1], - "timestamp": 40536.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [5, 14, 1], - "timestamp": 40537.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [5, 14, 2], - "timestamp": 40537.39999997616 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 40537.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [5, 14, 2], - "timestamp": 40538.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [5, 14, 3], - "timestamp": 40539.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [5, 14, 3], - "timestamp": 40541.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [5, 14, 4], - "timestamp": 40541.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [5, 14, 4], - "timestamp": 40541.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [5, 14, 5], - "timestamp": 40542 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [5, 14, 5], - "timestamp": 40542.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - } - }, - "path": [5, 14, 6], - "timestamp": 40543.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [5, 14, 6], - "timestamp": 47653.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [5, 14, 11], - "timestamp": 47659 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```", - "context": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [5, 14, 11], - "timestamp": 47660.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - }, - "path": [5, 14, 13], - "timestamp": 47661.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - }, - "path": [5, 14, 13], - "timestamp": 47664 - } - }, - { - "type": "graphend", - "data": { - "path": [5, 14], - "timestamp": 47664.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - }, - "validatorMetadata": [], - "path": [5, 14], - "timestamp": 47665.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - }, - "json": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - }, - "path": [5, 16], - "timestamp": 47666.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - }, - "json": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Tool that allows me to play and experiment with AI patterns\",\n \"justification\": \"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"\n },\n {\n \"requirement\": \"Ability to prototype quickly using Gemini APIs\",\n \"justification\": \"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"\n },\n {\n \"requirement\": \"Accessible AI that is easy for developers to use\",\n \"justification\": \"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"\n },\n {\n \"requirement\": \"Ability to create graphs with prompts\",\n \"justification\": \"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"\n }\n ]\n}\n```" - }, - "outputs": { - "json": { - "requirements": [ - { - "requirement": "Tool that allows me to play and experiment with AI patterns", - "justification": "As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects." - }, - { - "requirement": "Ability to prototype quickly using Gemini APIs", - "justification": "I need to be able to quickly and easily test out my AI ideas and see how they work in practice." - }, - { - "requirement": "Accessible AI that is easy for developers to use", - "justification": "I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects." - }, - { - "requirement": "Ability to create graphs with prompts", - "justification": "I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts." - } - ] - } - }, - "validatorMetadata": [], - "path": [5, 16], - "timestamp": 47677.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "json": { - "requirements": [ - { - "requirement": "Tool that allows me to play and experiment with AI patterns", - "justification": "As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects." - }, - { - "requirement": "Ability to prototype quickly using Gemini APIs", - "justification": "I need to be able to quickly and easily test out my AI ideas and see how they work in practice." - }, - { - "requirement": "Accessible AI that is easy for developers to use", - "justification": "I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects." - }, - { - "requirement": "Ability to create graphs with prompts", - "justification": "I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts." - } - ] - } - }, - "path": [5, 19], - "timestamp": 47679.19999998808 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [5, 19], - "timestamp": 47680.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [5, 19, 1], - "timestamp": 47680.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "json": { - "requirements": [ - { - "requirement": "Tool that allows me to play and experiment with AI patterns", - "justification": "As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects." - }, - { - "requirement": "Ability to prototype quickly using Gemini APIs", - "justification": "I need to be able to quickly and easily test out my AI ideas and see how they work in practice." - }, - { - "requirement": "Accessible AI that is easy for developers to use", - "justification": "I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects." - }, - { - "requirement": "Ability to create graphs with prompts", - "justification": "I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts." - } - ] - } - }, - "validatorMetadata": [], - "path": [5, 19, 1], - "timestamp": 47681.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "json": { - "requirements": [ - { - "requirement": "Tool that allows me to play and experiment with AI patterns", - "justification": "As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects." - }, - { - "requirement": "Ability to prototype quickly using Gemini APIs", - "justification": "I need to be able to quickly and easily test out my AI ideas and see how they work in practice." - }, - { - "requirement": "Accessible AI that is easy for developers to use", - "justification": "I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects." - }, - { - "requirement": "Ability to create graphs with prompts", - "justification": "I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts." - } - ] - } - }, - "path": [5, 19, 2], - "timestamp": 47681.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "json": { - "requirements": [ - { - "requirement": "Tool that allows me to play and experiment with AI patterns", - "justification": "As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects." - }, - { - "requirement": "Ability to prototype quickly using Gemini APIs", - "justification": "I need to be able to quickly and easily test out my AI ideas and see how they work in practice." - }, - { - "requirement": "Accessible AI that is easy for developers to use", - "justification": "I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects." - }, - { - "requirement": "Ability to create graphs with prompts", - "justification": "I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts." - } - ] - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ] - }, - "validatorMetadata": [], - "path": [5, 19, 2], - "timestamp": 47684.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ] - }, - "path": [5, 19, 3], - "timestamp": 47685.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ] - }, - "path": [5, 19, 3], - "timestamp": 47685.5 - } - }, - { - "type": "graphend", - "data": { - "path": [5, 19], - "timestamp": 47685.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "json": { - "requirements": [ - { - "requirement": "Tool that allows me to play and experiment with AI patterns", - "justification": "As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects." - }, - { - "requirement": "Ability to prototype quickly using Gemini APIs", - "justification": "I need to be able to quickly and easily test out my AI ideas and see how they work in practice." - }, - { - "requirement": "Accessible AI that is easy for developers to use", - "justification": "I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects." - }, - { - "requirement": "Ability to create graphs with prompts", - "justification": "I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts." - } - ] - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ] - }, - "validatorMetadata": [], - "path": [5, 19], - "timestamp": 47686.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "requirements": [ - { - "requirement": "Tool that allows me to play and experiment with AI patterns", - "justification": "As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects." - }, - { - "requirement": "Ability to prototype quickly using Gemini APIs", - "justification": "I need to be able to quickly and easily test out my AI ideas and see how they work in practice." - }, - { - "requirement": "Accessible AI that is easy for developers to use", - "justification": "I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects." - }, - { - "requirement": "Ability to create graphs with prompts", - "justification": "I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts." - } - ] - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ] - }, - "path": [5, 20], - "timestamp": 47686.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "requirements": [ - { - "requirement": "Tool that allows me to play and experiment with AI patterns", - "justification": "As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects." - }, - { - "requirement": "Ability to prototype quickly using Gemini APIs", - "justification": "I need to be able to quickly and easily test out my AI ideas and see how they work in practice." - }, - { - "requirement": "Accessible AI that is easy for developers to use", - "justification": "I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects." - }, - { - "requirement": "Ability to create graphs with prompts", - "justification": "I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts." - } - ] - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ] - }, - "path": [5, 20], - "timestamp": 47687.29999998212 - } - }, - { - "type": "graphend", - "data": { - "path": [5], - "timestamp": 47687.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-6", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - } - }, - "metadata": { - "title": "Customer", - "visual": { - "x": 820, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "requirements": [ - { - "requirement": "Tool that allows me to play and experiment with AI patterns", - "justification": "As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects." - }, - { - "requirement": "Ability to prototype quickly using Gemini APIs", - "justification": "I need to be able to quickly and easily test out my AI ideas and see how they work in practice." - }, - { - "requirement": "Accessible AI that is easy for developers to use", - "justification": "I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects." - }, - { - "requirement": "Ability to create graphs with prompts", - "justification": "I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts." - } - ] - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ] - }, - "validatorMetadata": [], - "path": [5], - "timestamp": 47688.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-7", - "type": "structuredWorker", - "configuration": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Editor", - "visual": { - "x": 1045, - "y": 71 - } - } - }, - "inputs": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ] - }, - "path": [7], - "timestamp": 47689.59999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext" - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext" - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count" - } - } - }, - "path": [7], - "timestamp": 47690.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [7, 1], - "timestamp": 47690.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ] - }, - "validatorMetadata": [], - "path": [7, 1], - "timestamp": 47691.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [7, 2], - "timestamp": 47691.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [7, 2], - "timestamp": 47692.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "path": [7, 3], - "timestamp": 47692.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "outputs": { - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "validatorMetadata": [], - "path": [7, 3], - "timestamp": 47693.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "path": [7, 9], - "timestamp": 47695.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [7, 9], - "timestamp": 47696.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ], - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [7, 10], - "timestamp": 47696.39999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [7, 10], - "timestamp": 47697.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [7, 10, 1], - "timestamp": 47697.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ], - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [7, 10, 1], - "timestamp": 47697.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ], - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [7, 10, 2], - "timestamp": 47698.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ], - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [7, 10, 2], - "timestamp": 47701.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [7, 10, 3], - "timestamp": 47702.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [7, 10, 3], - "timestamp": 47702.89999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [7, 10], - "timestamp": 47703.19999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ], - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [7, 10], - "timestamp": 47703.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [7, 11], - "timestamp": 47704 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [7, 11], - "timestamp": 47705.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [7, 11, 1], - "timestamp": 47705.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [7, 11, 1], - "timestamp": 47706.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [7, 11, 2], - "timestamp": 47706.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [7, 11, 2], - "timestamp": 47711 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [7, 11, 3], - "timestamp": 47711.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [7, 11, 3], - "timestamp": 47711.89999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [7, 11], - "timestamp": 47712.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [7, 11], - "timestamp": 47712.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [7, 14], - "timestamp": 47713.29999998212 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [7, 14], - "timestamp": 47714.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [7, 14, 1], - "timestamp": 47714.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [7, 14, 1], - "timestamp": 47715.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [7, 14, 2], - "timestamp": 47715.5 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 47715.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [7, 14, 2], - "timestamp": 47716.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [7, 14, 3], - "timestamp": 47717.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [7, 14, 3], - "timestamp": 47719.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [7, 14, 4], - "timestamp": 47719.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [7, 14, 4], - "timestamp": 47720.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [7, 14, 5], - "timestamp": 47720.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [7, 14, 5], - "timestamp": 47721.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "path": [7, 14, 6], - "timestamp": 47721.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [7, 14, 6], - "timestamp": 52854.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [7, 14, 11], - "timestamp": 52856.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}", - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [7, 14, 11], - "timestamp": 52858 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - }, - "path": [7, 14, 13], - "timestamp": 52858.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - }, - "path": [7, 14, 13], - "timestamp": 52859.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [7, 14], - "timestamp": 52859.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - }, - "validatorMetadata": [], - "path": [7, 14], - "timestamp": 52860.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - }, - "path": [7, 16], - "timestamp": 52861.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev Workflow with AI", - "Breadboard: Your AI Development Partner", - "Accelerate Innovation with Breadboard", - "Unlock AI's Power for Devs", - "Effortless AI Prototyping with Breadboard", - "Seamless Gemini API Integration", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Visualize Insights with AI Prompts", - "Revolutionize Dev Workflow with Breadboard", - "Empower Your Projects with AI", - "Breadboard: AI Development Simplified", - "Unleash Your AI Potential with Breadboard", - "Elevate Your Apps with AI Patterns", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "validatorMetadata": [], - "path": [7, 16], - "timestamp": 52870.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev Workflow with AI", - "Breadboard: Your AI Development Partner", - "Accelerate Innovation with Breadboard", - "Unlock AI's Power for Devs", - "Effortless AI Prototyping with Breadboard", - "Seamless Gemini API Integration", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Visualize Insights with AI Prompts", - "Revolutionize Dev Workflow with Breadboard", - "Empower Your Projects with AI", - "Breadboard: AI Development Simplified", - "Unleash Your AI Potential with Breadboard", - "Elevate Your Apps with AI Patterns", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "path": [7, 19], - "timestamp": 52872.19999998808 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [7, 19], - "timestamp": 52873.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [7, 19, 1], - "timestamp": 52873.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev Workflow with AI", - "Breadboard: Your AI Development Partner", - "Accelerate Innovation with Breadboard", - "Unlock AI's Power for Devs", - "Effortless AI Prototyping with Breadboard", - "Seamless Gemini API Integration", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Visualize Insights with AI Prompts", - "Revolutionize Dev Workflow with Breadboard", - "Empower Your Projects with AI", - "Breadboard: AI Development Simplified", - "Unleash Your AI Potential with Breadboard", - "Elevate Your Apps with AI Patterns", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "validatorMetadata": [], - "path": [7, 19, 1], - "timestamp": 52874 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev Workflow with AI", - "Breadboard: Your AI Development Partner", - "Accelerate Innovation with Breadboard", - "Unlock AI's Power for Devs", - "Effortless AI Prototyping with Breadboard", - "Seamless Gemini API Integration", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Visualize Insights with AI Prompts", - "Revolutionize Dev Workflow with Breadboard", - "Empower Your Projects with AI", - "Breadboard: AI Development Simplified", - "Unleash Your AI Potential with Breadboard", - "Elevate Your Apps with AI Patterns", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "path": [7, 19, 2], - "timestamp": 52874.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev Workflow with AI", - "Breadboard: Your AI Development Partner", - "Accelerate Innovation with Breadboard", - "Unlock AI's Power for Devs", - "Effortless AI Prototyping with Breadboard", - "Seamless Gemini API Integration", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Visualize Insights with AI Prompts", - "Revolutionize Dev Workflow with Breadboard", - "Empower Your Projects with AI", - "Breadboard: AI Development Simplified", - "Unleash Your AI Potential with Breadboard", - "Elevate Your Apps with AI Patterns", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [7, 19, 2], - "timestamp": 52877.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [7, 19, 3], - "timestamp": 52877.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [7, 19, 3], - "timestamp": 52878 - } - }, - { - "type": "graphend", - "data": { - "path": [7, 19], - "timestamp": 52878.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev Workflow with AI", - "Breadboard: Your AI Development Partner", - "Accelerate Innovation with Breadboard", - "Unlock AI's Power for Devs", - "Effortless AI Prototyping with Breadboard", - "Seamless Gemini API Integration", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Visualize Insights with AI Prompts", - "Revolutionize Dev Workflow with Breadboard", - "Empower Your Projects with AI", - "Breadboard: AI Development Simplified", - "Unleash Your AI Potential with Breadboard", - "Elevate Your Apps with AI Patterns", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [7, 19], - "timestamp": 52878.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev Workflow with AI", - "Breadboard: Your AI Development Partner", - "Accelerate Innovation with Breadboard", - "Unlock AI's Power for Devs", - "Effortless AI Prototyping with Breadboard", - "Seamless Gemini API Integration", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Visualize Insights with AI Prompts", - "Revolutionize Dev Workflow with Breadboard", - "Empower Your Projects with AI", - "Breadboard: AI Development Simplified", - "Unleash Your AI Potential with Breadboard", - "Elevate Your Apps with AI Patterns", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [7, 20], - "timestamp": 52879 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev Workflow with AI", - "Breadboard: Your AI Development Partner", - "Accelerate Innovation with Breadboard", - "Unlock AI's Power for Devs", - "Effortless AI Prototyping with Breadboard", - "Seamless Gemini API Integration", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Visualize Insights with AI Prompts", - "Revolutionize Dev Workflow with Breadboard", - "Empower Your Projects with AI", - "Breadboard: AI Development Simplified", - "Unleash Your AI Potential with Breadboard", - "Elevate Your Apps with AI Patterns", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [7, 20], - "timestamp": 52880.59999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [7], - "timestamp": 52881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-7", - "type": "structuredWorker", - "configuration": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Editor", - "visual": { - "x": 1045, - "y": 71 - } - } - }, - "inputs": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Supercharge Dev Workflow with AI", - "Breadboard: Your AI Development Partner", - "Accelerate Innovation with Breadboard", - "Unlock AI's Power for Devs", - "Effortless AI Prototyping with Breadboard", - "Seamless Gemini API Integration", - "Unlock the Potential of AI for Developers", - "Breadboard: Your AI Co-pilot", - "Visualize Insights with AI Prompts", - "Revolutionize Dev Workflow with Breadboard", - "Empower Your Projects with AI", - "Breadboard: AI Development Simplified", - "Unleash Your AI Potential with Breadboard", - "Elevate Your Apps with AI Patterns", - "AI at Your Fingertips with Breadboard" - ], - "descriptions": [ - "Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.", - "Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.", - "Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.", - "Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [7], - "timestamp": 52881.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "repeater-8", - "type": "repeater", - "configuration": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4 - }, - "metadata": { - "title": "Ad refinery", - "visual": { - "x": 1250, - "y": 71 - } - } - }, - "inputs": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [8], - "timestamp": 52883 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=repeater", - "title": "Repeater", - "description": "A worker whose job it is to repeat the same thing over and over, until some condition is met or the max count of repetitions is reached.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "counter", - "to": "invokeAgent", - "out": "continue", - "in": "context" - }, - { - "from": "counter", - "to": "counter", - "out": "count", - "in": "count" - }, - { - "from": "counter", - "to": "output-2", - "out": "stop", - "in": "context" - }, - { - "from": "invokeAgent", - "to": "exit", - "out": "exit", - "in": "context" - }, - { - "from": "invokeAgent", - "to": "counter", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "invokeAgent", - "out": "worker", - "in": "$board", - "constant": true - }, - { - "from": "input-1", - "to": "invokeAgent", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "counter", - "out": "max", - "in": "count" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "worker": { - "title": "Worker", - "behavior": ["board"], - "description": "Worker to repeat", - "type": "object" - }, - "context": { - "title": "Context", - "type": "array", - "format": "multiline", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "description": "Initial conversation context" - }, - "max": { - "title": "Max", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "type": "number", - "default": "-1", - "examples": ["3"] - } - }, - "required": ["worker"] - } - } - }, - { - "id": "exit", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Exit", - "description": "Exiting early from the repeater" - } - } - ], - "kits": [], - "graphs": { - "counter": { - "edges": [ - { - "from": "counter-input", - "to": "counter-run", - "out": "*" - }, - { - "from": "counter-run", - "to": "counter-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - { - "id": "counter-output", - "type": "output", - "configuration": {} - } - ] - } - } - }, - "path": [8], - "timestamp": 52884.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "worker": { - "title": "Worker", - "behavior": ["board"], - "description": "Worker to repeat", - "type": "object" - }, - "context": { - "title": "Context", - "type": "array", - "format": "multiline", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "description": "Initial conversation context" - }, - "max": { - "title": "Max", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "type": "number", - "default": "-1", - "examples": ["3"] - } - }, - "required": ["worker"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "worker": { - "title": "Worker", - "behavior": ["board"], - "description": "Worker to repeat", - "type": "object" - }, - "context": { - "title": "Context", - "type": "array", - "format": "multiline", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "description": "Initial conversation context" - }, - "max": { - "title": "Max", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "type": "number", - "default": "-1", - "examples": ["3"] - } - }, - "required": ["worker"] - } - }, - "path": [8, 1], - "timestamp": 52884.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "worker": { - "title": "Worker", - "behavior": ["board"], - "description": "Worker to repeat", - "type": "object" - }, - "context": { - "title": "Context", - "type": "array", - "format": "multiline", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "description": "Initial conversation context" - }, - "max": { - "title": "Max", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "type": "number", - "default": "-1", - "examples": ["3"] - } - }, - "required": ["worker"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "worker": { - "title": "Worker", - "behavior": ["board"], - "description": "Worker to repeat", - "type": "object" - }, - "context": { - "title": "Context", - "type": "array", - "format": "multiline", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "description": "Initial conversation context" - }, - "max": { - "title": "Max", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "type": "number", - "default": "-1", - "examples": ["3"] - } - }, - "required": ["worker"] - } - }, - "outputs": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 1], - "timestamp": 52885.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [8, 2], - "timestamp": 52886 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "kits": [], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - }, - "path": [8, 2], - "timestamp": 52887 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "path": [8, 2, 1], - "timestamp": 52887.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 1], - "timestamp": 52888.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [8, 2, 2], - "timestamp": 52888.69999998808 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 2, 2], - "timestamp": 52889.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 2, 2, 1], - "timestamp": 52890.19999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 2, 1], - "timestamp": 52890.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "path": [8, 2, 2, 2], - "timestamp": 52891.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 2, 2, 2], - "timestamp": 52895.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - "path": [8, 2, 2, 3], - "timestamp": 52895.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - "path": [8, 2, 2, 3], - "timestamp": 52896.09999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 2], - "timestamp": 52896.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 2, 2], - "timestamp": 52896.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - "path": [8, 2, 3], - "timestamp": 52897 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext" - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext" - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count" - } - } - }, - "path": [8, 2, 3], - "timestamp": 52897.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [8, 2, 3, 1], - "timestamp": 52898.19999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 2, 3, 1], - "timestamp": 52898.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [8, 2, 3, 2], - "timestamp": 52898.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 2], - "timestamp": 52899.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "path": [8, 2, 3, 3], - "timestamp": 52899.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "outputs": { - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 3], - "timestamp": 52900 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "path": [8, 2, 3, 9], - "timestamp": 52902.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 9], - "timestamp": 52902.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [8, 2, 3, 10], - "timestamp": 52903 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 2, 3, 10], - "timestamp": 52903.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 2, 3, 10, 1], - "timestamp": 52903.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 10, 1], - "timestamp": 52904.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [8, 2, 3, 10, 2], - "timestamp": 52904.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 3, 10, 2], - "timestamp": 52907.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 2, 3, 10, 3], - "timestamp": 52907.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 2, 3, 10, 3], - "timestamp": 52907.89999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 3, 10], - "timestamp": 52908.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 3, 10], - "timestamp": 52908.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [8, 2, 3, 11], - "timestamp": 52908.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 2, 3, 11], - "timestamp": 52909.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 2, 3, 11, 1], - "timestamp": 52910.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 11, 1], - "timestamp": 52910.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [8, 2, 3, 11, 2], - "timestamp": 52911.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [8, 2, 3, 11, 2], - "timestamp": 52915.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [8, 2, 3, 11, 3], - "timestamp": 52916.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [8, 2, 3, 11, 3], - "timestamp": 52916.79999998212 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 3, 11], - "timestamp": 52917.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [8, 2, 3, 11], - "timestamp": 52917.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 2, 3, 14], - "timestamp": 52918.59999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [8, 2, 3, 14], - "timestamp": 52919.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [8, 2, 3, 14, 1], - "timestamp": 52919.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 1], - "timestamp": 52920.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [8, 2, 3, 14, 2], - "timestamp": 52920.59999999404 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 52921.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 2], - "timestamp": 52922.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [8, 2, 3, 14, 3], - "timestamp": 52923.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 3], - "timestamp": 52926 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [8, 2, 3, 14, 4], - "timestamp": 52926.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 4], - "timestamp": 52926.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [8, 2, 3, 14, 5], - "timestamp": 52927.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 5], - "timestamp": 52928.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "path": [8, 2, 3, 14, 6], - "timestamp": 52928.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 6], - "timestamp": 55909.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [8, 2, 3, 14, 11], - "timestamp": 55914.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}", - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 11], - "timestamp": 55916.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - }, - "path": [8, 2, 3, 14, 13], - "timestamp": 55917.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - }, - "path": [8, 2, 3, 14, 13], - "timestamp": 55918.29999998212 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 3, 14], - "timestamp": 55918.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14], - "timestamp": 55919.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - }, - "path": [8, 2, 3, 16], - "timestamp": 55920.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 16], - "timestamp": 55930.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "path": [8, 2, 3, 19], - "timestamp": 55932.19999998808 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 2, 3, 19], - "timestamp": 55933.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 2, 3, 19, 1], - "timestamp": 55933.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 19, 1], - "timestamp": 55934.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "path": [8, 2, 3, 19, 2], - "timestamp": 55934.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 3, 19, 2], - "timestamp": 55939.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 2, 3, 19, 3], - "timestamp": 55940.19999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 2, 3, 19, 3], - "timestamp": 55940.79999998212 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 3, 19], - "timestamp": 55941.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 3, 19], - "timestamp": 55941.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 2, 3, 20], - "timestamp": 55942.19999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 2, 3, 20], - "timestamp": 55942.69999998808 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 3], - "timestamp": 55943.19999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 3], - "timestamp": 55943.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 2, 6], - "timestamp": 55944.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 2, 6], - "timestamp": 55945.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2], - "timestamp": 55945.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2], - "timestamp": 55946.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - "inputs": { - "$board": "#counter", - "count": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 4], - "timestamp": 55947.09999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=repeater#counter", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "counter-input", - "to": "counter-run", - "out": "*" - }, - { - "from": "counter-run", - "to": "counter-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - { - "id": "counter-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 4], - "timestamp": 55948.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 4, 1], - "timestamp": 55949 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "count": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 4, 1], - "timestamp": 55949.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - "inputs": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true, - "count": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 4, 2], - "timestamp": 55949.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - "inputs": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true, - "count": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ], - "count": 3 - }, - "validatorMetadata": [], - "path": [8, 4, 2], - "timestamp": 55953.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ], - "count": 3 - }, - "path": [8, 4, 3], - "timestamp": 55954.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ], - "count": 3 - }, - "path": [8, 4, 3], - "timestamp": 55955.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 4], - "timestamp": 55956 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - "inputs": { - "$board": "#counter", - "count": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ], - "count": 3 - }, - "validatorMetadata": [], - "path": [8, 4], - "timestamp": 55956.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 7], - "timestamp": 55958.09999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "kits": [], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - }, - "path": [8, 7], - "timestamp": 55959.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "path": [8, 7, 1], - "timestamp": 55960 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 7, 1], - "timestamp": 55960.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 7, 2], - "timestamp": 55961.19999998808 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 7, 2], - "timestamp": 55961.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 7, 2, 1], - "timestamp": 55962.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 7, 2, 1], - "timestamp": 55963.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 7, 2, 2], - "timestamp": 55964.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 7, 2, 2], - "timestamp": 55969.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 7, 2, 3], - "timestamp": 55970.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 7, 2, 3], - "timestamp": 55971.19999998808 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 7, 2], - "timestamp": 55971.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 7, 2], - "timestamp": 55971.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - }, - "exit": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 7, 5], - "timestamp": 55973.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - }, - "exit": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 7, 5], - "timestamp": 55973.5 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 7], - "timestamp": 55973.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - }, - "exit": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 7], - "timestamp": 55974.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "exit", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Exit", - "description": "Exiting early from the repeater" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 10], - "timestamp": 55975.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "exit", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Exit", - "description": "Exiting early from the repeater" - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [8, 10], - "timestamp": 55976.29999998212 - } - }, - { - "type": "graphend", - "data": { - "path": [8], - "timestamp": 55976.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "repeater-8", - "type": "repeater", - "configuration": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4 - }, - "metadata": { - "title": "Ad refinery", - "visual": { - "x": 1250, - "y": 71 - } - } - }, - "inputs": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8], - "timestamp": 55977.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-9", - "type": "invoke", - "configuration": { - "$board": "#fn-9" - }, - "metadata": { - "title": "JSON Extractor", - "visual": { - "x": 1443, - "y": 177 - } - } - }, - "inputs": { - "$board": "#fn-9", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [9], - "timestamp": 55978.29999998212 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "http://localhost:5173/graphs/ad-writer-2.json#fn-9", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "fn-9-input", - "to": "fn-9-run", - "out": "*" - }, - { - "from": "fn-9-run", - "to": "fn-9-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-9-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-9-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true - } - }, - { - "id": "fn-9-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [9], - "timestamp": 55979.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-9-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [9, 1], - "timestamp": 55979.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-9-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [9, 1], - "timestamp": 55980.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-9-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true - } - }, - "inputs": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "path": [9, 2], - "timestamp": 55980.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-9-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true - } - }, - "inputs": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "validatorMetadata": [], - "path": [9, 2], - "timestamp": 55984.29999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-9-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "path": [9, 3], - "timestamp": 55984.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-9-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "path": [9, 3], - "timestamp": 55985.69999998808 - } - }, - { - "type": "graphend", - "data": { - "path": [9], - "timestamp": 55986.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-9", - "type": "invoke", - "configuration": { - "$board": "#fn-9" - }, - "metadata": { - "title": "JSON Extractor", - "visual": { - "x": 1443, - "y": 177 - } - } - }, - "inputs": { - "$board": "#fn-9", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ] - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "validatorMetadata": [], - "path": [9], - "timestamp": 55986.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - } - }, - "metadata": { - "visual": { - "x": 1626, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "path": [10], - "timestamp": 55987.39999997616 - } - }, - { - "type": "output", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - } - }, - "metadata": { - "visual": { - "x": 1626, - "y": 71 - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "path": [10], - "timestamp": 55988.29999998212, - "bubbled": false - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - } - }, - "metadata": { - "visual": { - "x": 1626, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev with Accessible AI\",\"Breadboard: The AI Playground for Devs\",\"Play, Experiment, Prototype with Ease\",\"Unlock AI's Power with Gemini APIs\",\"Transform Ideas into Reality with AI\",\"Graph Anything with AI Prompts\",\"Empowering Devs with AI-Powered Solutions\",\"Prototype in Minutes with Breadboard\",\"Integrate AI into Your Projects Seamlessly\",\"Breadboard: AI Development Simplified\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Accelerate App Development with AI Patterns\",\"Revolutionize Dev Workflow with Breadboard\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are an experienced software developer. You are skeptical of ads and weary of being sold to, but you are willing to provide constructive feedback. You are interested in learning more about AI and how to integrate it into your projects. You are looking for a tool that will allow you to play and experiment with AI patterns and prototype quickly using Gemini APIs. You want to be able to create graphs with prompts and access AI in a way that is accessible to you as a developer." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Tool that allows me to play and experiment with AI patterns\",\"justification\":\"As a developer, I need to be able to explore and understand the capabilities of AI before committing to using it in my projects.\"},{\"requirement\":\"Ability to prototype quickly using Gemini APIs\",\"justification\":\"I need to be able to quickly and easily test out my AI ideas and see how they work in practice.\"},{\"requirement\":\"Accessible AI that is easy for developers to use\",\"justification\":\"I don't want to have to spend a lot of time learning about AI before I can start using it. I need a tool that is designed for developers and that makes it easy to integrate AI into my projects.\"},{\"requirement\":\"Ability to create graphs with prompts\",\"justification\":\"I often need to visualize data in order to understand it. I need a tool that allows me to easily create graphs using AI prompts.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Supercharge Dev Workflow with AI\",\"Breadboard: Your AI Development Partner\",\"Accelerate Innovation with Breadboard\",\"Unlock AI's Power for Devs\",\"Effortless AI Prototyping with Breadboard\",\"Seamless Gemini API Integration\",\"Unlock the Potential of AI for Developers\",\"Breadboard: Your AI Co-pilot\",\"Visualize Insights with AI Prompts\",\"Revolutionize Dev Workflow with Breadboard\",\"Empower Your Projects with AI\",\"Breadboard: AI Development Simplified\",\"Unleash Your AI Potential with Breadboard\",\"Elevate Your Apps with AI Patterns\",\"AI at Your Fingertips with Breadboard\"],\"descriptions\":[\"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\",\"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\",\"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\",\"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Supercharge Dev Workflow with AI\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Your AI Development Partner\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Innovation with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Effortless AI Prototyping with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Seamless Gemini API Integration\" is 31 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Potential of AI for Developers\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize Insights with AI Prompts\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Revolutionize Dev Workflow with Breadboard\" is 42 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Development Simplified\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unleash Your AI Potential with Breadboard\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Elevate Your Apps with AI Patterns\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"AI at Your Fingertips with Breadboard\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to harness the power of AI. Play with AI patterns, prototype quickly, and integrate AI into projects with ease.\" is 142 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Gemini APIs provide seamless access to AI capabilities. Use Breadboard to unlock the full potential of AI and create innovative solutions.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes it easy to create graphs using AI prompts. Visualize data, explore insights, and uncover patterns in a matter of seconds.\" is 138 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard is the ultimate tool for developers looking to integrate AI into their projects. With its intuitive interface and powerful integrations, you can bring your AI-powered ideas to life.\" is 192 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Power Up Dev with AI\",\"Breadboard: Your AI Ally\",\"Speed Up Innovation\",\"Effortless AI Prototyping\",\"Gemini API Integration\",\"Unlock AI's Power\",\"Visualize Data with AI\",\"Revolutionize Dev Workflow\",\"Breadboard: AI Made Easy\",\"Unleash Your AI Potential\",\"Boost Apps with AI\",\"AI Within Reach\"],\"descriptions\":[\"Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.\",\"Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.\",\"Visualize Insights with AI. Breadboard makes it a breeze.\",\"Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly.\"]}}" - } - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Power Up Dev with AI", - "Breadboard: Your AI Ally", - "Speed Up Innovation", - "Effortless AI Prototyping", - "Gemini API Integration", - "Unlock AI's Power", - "Visualize Data with AI", - "Revolutionize Dev Workflow", - "Breadboard: AI Made Easy", - "Unleash Your AI Potential", - "Boost Apps with AI", - "AI Within Reach" - ], - "descriptions": [ - "Breadboard: Empowering Devs with AI. Experiment, prototype, and integrate AI seamlessly.", - "Unlock AI's Potential with Breadboard. Gemini API integration makes it easy.", - "Visualize Insights with AI. Breadboard makes it a breeze.", - "Breadboard: Your AI Toolkit. Build AI-powered solutions effortlessly." - ] - } - } - }, - "validatorMetadata": [], - "path": [10], - "timestamp": 55988.69999998808 - } - }, - { - "type": "graphend", - "data": { - "path": [], - "timestamp": 55992.5 - } - } -] diff --git a/packages/breadboard/tests/inspector/data/loader/ad-writer-2.2.raw.json b/packages/breadboard/tests/inspector/data/loader/ad-writer-2.2.raw.json deleted file mode 100644 index a5540336304..00000000000 --- a/packages/breadboard/tests/inspector/data/loader/ad-writer-2.2.raw.json +++ /dev/null @@ -1,63833 +0,0 @@ -[ - { - "type": "graphstart", - "data": { - "graph": { - "url": "http://localhost:5173/graphs/ad-writer-2.json", - "title": "Ad Writer (variant 2)", - "description": "An example of chain of agents working on writing an ad", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "repeater-8", - "to": "fn-9", - "out": "context", - "in": "context" - }, - { - "from": "repeater-8", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-9", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "structuredWorker-7", - "to": "repeater-8", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-6", - "to": "structuredWorker-7", - "out": "context", - "in": "context" - }, - { - "from": "fn-5", - "to": "structuredWorker-6", - "out": "prompt", - "in": "instruction" - }, - { - "from": "structuredWorker-4", - "to": "structuredWorker-6", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-3", - "to": "fn-5", - "out": "json", - "in": "json" - }, - { - "from": "input-1", - "to": "structuredWorker-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - } - }, - "metadata": { - "visual": { - "x": 1626, - "y": 71 - } - } - }, - { - "id": "repeater-8", - "type": "repeater", - "configuration": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4 - }, - "metadata": { - "title": "Ad refinery", - "visual": { - "x": 1250, - "y": 71 - } - } - }, - { - "id": "fn-9", - "type": "invoke", - "configuration": { - "$board": "#fn-9" - }, - "metadata": { - "title": "JSON Extractor", - "visual": { - "x": 1443, - "y": 177 - } - } - }, - { - "id": "structuredWorker-7", - "type": "structuredWorker", - "configuration": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Editor", - "visual": { - "x": 1045, - "y": 71 - } - } - }, - { - "id": "structuredWorker-6", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - } - }, - "metadata": { - "title": "Customer", - "visual": { - "x": 820, - "y": 71 - } - } - }, - { - "id": "fn-5", - "type": "invoke", - "configuration": { - "$board": "#fn-5" - }, - "metadata": { - "title": "Prompt Extractor", - "visual": { - "x": 595, - "y": 71 - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Writer", - "visual": { - "x": 595, - "y": 263 - } - } - }, - { - "id": "structuredWorker-3", - "type": "structuredWorker", - "configuration": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - } - }, - "metadata": { - "title": "Customer Prompt Maker", - "description": "Conjuring up a persona to represent a customer", - "logLevel": "info", - "visual": { - "x": 331, - "y": 71 - } - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "metadata": { - "visual": { - "x": 77, - "y": 71 - } - } - } - ], - "kits": [], - "graphs": { - "fn-9": { - "edges": [ - { - "from": "fn-9-input", - "to": "fn-9-run", - "out": "*" - }, - { - "from": "fn-9-run", - "to": "fn-9-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-9-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-9-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true - } - }, - { - "id": "fn-9-output", - "type": "output", - "configuration": {} - } - ], - "url": "http://localhost:5173/graphs/ad-writer-2.json#fn-9" - }, - "fn-5": { - "edges": [ - { - "from": "fn-5-input", - "to": "fn-5-run", - "out": "*" - }, - { - "from": "fn-5-run", - "to": "fn-5-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-5-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-5-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true - } - }, - { - "id": "fn-5-output", - "type": "output", - "configuration": {} - } - ], - "url": "http://localhost:5173/graphs/ad-writer-2.json#fn-5" - } - } - }, - "path": [], - "timestamp": 260297 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "metadata": { - "visual": { - "x": 77, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "path": [1], - "timestamp": 260300.09999999404 - } - }, - { - "type": "input", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "metadata": { - "visual": { - "x": 77, - "y": 71 - } - } - }, - "inputArguments": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "path": [1], - "bubbled": false, - "timestamp": 260303.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "metadata": { - "visual": { - "x": 77, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Ad specs", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - ], - "format": "multiline" - } - }, - "required": ["context"] - } - }, - "outputs": { - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "validatorMetadata": [], - "path": [1], - "timestamp": 261927.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-3", - "type": "structuredWorker", - "configuration": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - } - }, - "metadata": { - "title": "Customer Prompt Maker", - "description": "Conjuring up a persona to represent a customer", - "logLevel": "info", - "visual": { - "x": 331, - "y": 71 - } - } - }, - "inputs": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "path": [2], - "timestamp": 261928.69999998808 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ] - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ] - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ] - } - } - }, - "path": [2], - "timestamp": 261930.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [2, 1], - "timestamp": 261931.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "validatorMetadata": [], - "path": [2, 1], - "timestamp": 261933.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [2, 2], - "timestamp": 261934 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [2, 2], - "timestamp": 261934.69999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - } - }, - "path": [2, 3], - "timestamp": 261934.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - } - }, - "outputs": { - "schemish": { - "prompt": "string, the prompt for the bot" - } - }, - "validatorMetadata": [], - "path": [2, 3], - "timestamp": 261935.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "prompt": "string, the prompt for the bot" - } - }, - "path": [2, 9], - "timestamp": 261936.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "prompt": "string, the prompt for the bot" - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "validatorMetadata": [], - "path": [2, 9], - "timestamp": 261937.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "path": [2, 10], - "timestamp": 261937.29999998212 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [2, 10], - "timestamp": 261937.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [2, 10, 1], - "timestamp": 261938.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "validatorMetadata": [], - "path": [2, 10, 1], - "timestamp": 261938.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "path": [2, 10, 2], - "timestamp": 261938.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [2, 10, 2], - "timestamp": 261943.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [2, 10, 3], - "timestamp": 261943.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [2, 10, 3], - "timestamp": 261943.69999998808 - } - }, - { - "type": "graphend", - "data": { - "path": [2, 10], - "timestamp": 261943.79999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [2, 10], - "timestamp": 261943.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [2, 11], - "timestamp": 261944 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [2, 11], - "timestamp": 261944.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [2, 11, 1], - "timestamp": 261945 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [2, 11, 1], - "timestamp": 261945.19999998808 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [2, 11, 2], - "timestamp": 261945.29999998212 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [2, 11, 2], - "timestamp": 261948.79999998212 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "path": [2, 11, 3], - "timestamp": 261949.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "path": [2, 11, 3], - "timestamp": 261949.29999998212 - } - }, - { - "type": "graphend", - "data": { - "path": [2, 11], - "timestamp": 261949.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [2, 11], - "timestamp": 261949.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [2, 14], - "timestamp": 261950 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [2, 14], - "timestamp": 261950.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [2, 14, 1], - "timestamp": 261951.29999998212 - } - }, - { - "type": "input", - "data": { - "node": { - "id": "parameters", - "type": "input" - }, - "inputArguments": { - "schema": { - "type": "object", - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - } - } - } - }, - "path": [2, 14, 1], - "bubbled": true, - "timestamp": 261951.69999998808 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [2, 14, 1], - "timestamp": 263262.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [2, 14, 2], - "timestamp": 263265.39999997616 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 263266.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [2, 14, 2], - "timestamp": 263267.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [2, 14, 3], - "timestamp": 263269.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [2, 14, 3], - "timestamp": 263274.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [2, 14, 4], - "timestamp": 263275.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [2, 14, 4], - "timestamp": 263276.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [2, 14, 5], - "timestamp": 263276.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [2, 14, 5], - "timestamp": 263280.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "path": [2, 14, 6], - "timestamp": 263280.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [2, 14, 6], - "timestamp": 273331.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [2, 14, 11], - "timestamp": 273335.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```", - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [2, 14, 11], - "timestamp": 273337.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - }, - "path": [2, 14, 13], - "timestamp": 273338.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - }, - "path": [2, 14, 13], - "timestamp": 273339.09999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [2, 14], - "timestamp": 273339.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - }, - "validatorMetadata": [], - "path": [2, 14], - "timestamp": 273339.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "json": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - }, - "path": [2, 16], - "timestamp": 273340 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "json": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - }, - "outputs": { - "$error": { - "kind": "error", - "error": { - "type": "parsing", - "message": "Bad escaped character in JSON at position 140 (line 2 column 139)" - } - } - }, - "validatorMetadata": [], - "path": [2, 16], - "timestamp": 273341.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4, - "error": { - "descriptor": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "kind": "error", - "error": { - "type": "parsing", - "message": "Bad escaped character in JSON at position 140 (line 2 column 139)" - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "json": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - } - }, - "path": [2, 17], - "timestamp": 273342.1999999881 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [2, 17], - "timestamp": 273343.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [2, 17, 1], - "timestamp": 273343.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4, - "error": { - "descriptor": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "kind": "error", - "error": { - "type": "parsing", - "message": "Bad escaped character in JSON at position 140 (line 2 column 139)" - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "json": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - } - }, - "validatorMetadata": [], - "path": [2, 17, 1], - "timestamp": 273344 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4, - "error": { - "descriptor": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "kind": "error", - "error": { - "type": "parsing", - "message": "Bad escaped character in JSON at position 140 (line 2 column 139)" - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "json": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - } - }, - "path": [2, 17, 2], - "timestamp": 273344.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4, - "error": { - "descriptor": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "kind": "error", - "error": { - "type": "parsing", - "message": "Bad escaped character in JSON at position 140 (line 2 column 139)" - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "json": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - } - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 3 - }, - "validatorMetadata": [], - "path": [2, 17, 2], - "timestamp": 273348.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 3 - }, - "path": [2, 17, 3], - "timestamp": 273349.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 3 - }, - "path": [2, 17, 3], - "timestamp": 273349.7999999821 - } - }, - { - "type": "graphend", - "data": { - "path": [2, 17], - "timestamp": 273350 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4, - "error": { - "descriptor": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "kind": "error", - "error": { - "type": "parsing", - "message": "Bad escaped character in JSON at position 140 (line 2 column 139)" - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "json": "```json\n{\n \"prompt\": \"You are a skeptical developer. You are agnostic towards ads but you are extremely likely to help improve marketing content. \\\n I'd like you to pretend to be the target audience for the following ad and respond as you would. \\\n You should incorporate the sense of skepticism and weariness of ads yet the willingness to provide constructive feedback.\\n\\n---\\n\\n**Headline:** Breadboard for Developers\\n\\n**Body:** Build AI-powered apps quickly with Breadboard for Developers. \\\n It's the fastest way to prototype AI-powered apps, play with new AI patterns, and integrate AI into your next project. \\\n With Breadboard, you can:\\n\\n- Use Gemini APIs: experiment with AI patterns from OpenAI, Cohere, and more.\\n- Create graphs with prompts: visualize data and relationships between concepts.\\n- Prototype quickly: build and test AI apps in minutes, without writing any code.\\n\\nGet started for free today!\"\n}\n```" - } - } - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 3 - }, - "validatorMetadata": [], - "path": [2, 17], - "timestamp": 273350.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [2, 20], - "timestamp": 273350.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [2, 20], - "timestamp": 273352 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [2, 20, 1], - "timestamp": 273352.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [2, 20, 1], - "timestamp": 273352.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [2, 20, 2], - "timestamp": 273353.1999999881 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 273353.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [2, 20, 2], - "timestamp": 273354.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [2, 20, 3], - "timestamp": 273356.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [2, 20, 3], - "timestamp": 273360 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [2, 20, 4], - "timestamp": 273360.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [2, 20, 4], - "timestamp": 273360.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [2, 20, 5], - "timestamp": 273360.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [2, 20, 5], - "timestamp": 273361.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "path": [2, 20, 6], - "timestamp": 273361.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [2, 20, 6], - "timestamp": 276399.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [2, 20, 11], - "timestamp": 276403.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```", - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [2, 20, 11], - "timestamp": 276406.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - }, - "path": [2, 20, 13], - "timestamp": 276407.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - }, - "path": [2, 20, 13], - "timestamp": 276407.6999999881 - } - }, - { - "type": "graphend", - "data": { - "path": [2, 20], - "timestamp": 276408.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - }, - "validatorMetadata": [], - "path": [2, 20], - "timestamp": 276408.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "json": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - }, - "path": [2, 22], - "timestamp": 276409.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "json": "```json\n{\n \"prompt\": \"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"\n}\n```" - }, - "outputs": { - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - }, - "validatorMetadata": [], - "path": [2, 22], - "timestamp": 276444.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - }, - "path": [2, 25], - "timestamp": 276444.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [2, 25], - "timestamp": 276445.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [2, 25, 1], - "timestamp": 276445.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - }, - "validatorMetadata": [], - "path": [2, 25, 1], - "timestamp": 276446.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - }, - "path": [2, 25, 2], - "timestamp": 276446.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"}" - } - } - ] - }, - "validatorMetadata": [], - "path": [2, 25, 2], - "timestamp": 276449.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"}" - } - } - ] - }, - "path": [2, 25, 3], - "timestamp": 276450 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"}" - } - } - ] - }, - "path": [2, 25, 3], - "timestamp": 276450.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [2, 25], - "timestamp": 276450.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"}" - } - } - ] - }, - "validatorMetadata": [], - "path": [2, 25], - "timestamp": 276450.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"}" - } - } - ] - }, - "path": [2, 26], - "timestamp": 276450.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"}" - } - } - ] - }, - "path": [2, 26], - "timestamp": 276451.59999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [2], - "timestamp": 276451.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-3", - "type": "structuredWorker", - "configuration": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - } - }, - "metadata": { - "title": "Customer Prompt Maker", - "description": "Conjuring up a persona to represent a customer", - "logLevel": "info", - "visual": { - "x": 331, - "y": 71 - } - } - }, - "inputs": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"prompt\": \"string, the prompt for the bot\"\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"prompt\":\"You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\\n\\nAs this persona, reply to an ad for Breadboard with the following key messages:\\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs\\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"}" - } - } - ] - }, - "validatorMetadata": [], - "path": [2], - "timestamp": 276452.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Writer", - "visual": { - "x": 595, - "y": 263 - } - } - }, - "inputs": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "path": [3], - "timestamp": 276453.1999999881 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext" - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext" - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count" - } - } - }, - "path": [3], - "timestamp": 276454.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [3, 1], - "timestamp": 276454.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "validatorMetadata": [], - "path": [3, 1], - "timestamp": 276454.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [3, 2], - "timestamp": 276455 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [3, 2], - "timestamp": 276455.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "path": [3, 3], - "timestamp": 276455.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "outputs": { - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "validatorMetadata": [], - "path": [3, 3], - "timestamp": 276455.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "path": [3, 9], - "timestamp": 276456.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [3, 9], - "timestamp": 276457.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [3, 10], - "timestamp": 276457.39999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [3, 10], - "timestamp": 276457.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [3, 10, 1], - "timestamp": 276458 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [3, 10, 1], - "timestamp": 276458.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [3, 10, 2], - "timestamp": 276458.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [3, 10, 2], - "timestamp": 276462.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [3, 10, 3], - "timestamp": 276462.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [3, 10, 3], - "timestamp": 276462.89999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [3, 10], - "timestamp": 276463 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [3, 10], - "timestamp": 276463.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [3, 11], - "timestamp": 276463.39999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [3, 11], - "timestamp": 276464.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [3, 11, 1], - "timestamp": 276464.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [3, 11, 1], - "timestamp": 276464.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [3, 11, 2], - "timestamp": 276464.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [3, 11, 2], - "timestamp": 276466.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "path": [3, 11, 3], - "timestamp": 276467 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "path": [3, 11, 3], - "timestamp": 276467.1999999881 - } - }, - { - "type": "graphend", - "data": { - "path": [3, 11], - "timestamp": 276467.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [3, 11], - "timestamp": 276467.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "path": [3, 14], - "timestamp": 276468 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [3, 14], - "timestamp": 276468.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [3, 14, 1], - "timestamp": 276469 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [3, 14, 1], - "timestamp": 276469.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [3, 14, 2], - "timestamp": 276469.5 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 276469.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [3, 14, 2], - "timestamp": 276470.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [3, 14, 3], - "timestamp": 276471 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [3, 14, 3], - "timestamp": 276473.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [3, 14, 4], - "timestamp": 276473.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [3, 14, 4], - "timestamp": 276474.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [3, 14, 5], - "timestamp": 276474.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [3, 14, 5], - "timestamp": 276474.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "path": [3, 14, 6], - "timestamp": 276475.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [3, 14, 6], - "timestamp": 282901.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [3, 14, 11], - "timestamp": 282906.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```", - "context": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [3, 14, 11], - "timestamp": 282908.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - }, - "path": [3, 14, 13], - "timestamp": 282910.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - }, - "path": [3, 14, 13], - "timestamp": 282911 - } - }, - { - "type": "graphend", - "data": { - "path": [3, 14], - "timestamp": 282911.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - }, - "validatorMetadata": [], - "path": [3, 14], - "timestamp": 282911.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - }, - "path": [3, 16], - "timestamp": 282912.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"Developers, Revolutionize AI with Breadboard!\",\n \"Unlock the Power of AI with Breadboard's Playground\",\n \"Prototype AI Solutions in a Flash with Breadboard\",\n \"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\n \"Empower Your Projects with Breadboard's Accessible AI\",\n \"Visualize AI Insights with Breadboard's Graph Creation\",\n \"Breadboard: Where Developers and AI Unite\",\n \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\n \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\n \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\n \"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\n \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\n \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\n \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\n \"Breadboard: Empowering Developers to Build the Future of AI\"\n ],\n \"descriptions\": [\n \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\n \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\n \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\n \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"\n ]\n }\n}\n```" - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "validatorMetadata": [], - "path": [3, 16], - "timestamp": 282924.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "path": [3, 19], - "timestamp": 282926.1999999881 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [3, 19], - "timestamp": 282927.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [3, 19, 1], - "timestamp": 282927.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "validatorMetadata": [], - "path": [3, 19, 1], - "timestamp": 282928.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "path": [3, 19, 2], - "timestamp": 282928.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [3, 19, 2], - "timestamp": 282932.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [3, 19, 3], - "timestamp": 282933.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [3, 19, 3], - "timestamp": 282933.59999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [3, 19], - "timestamp": 282933.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [3, 19], - "timestamp": 282934.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [3, 20], - "timestamp": 282934.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [3, 20], - "timestamp": 282935.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [3], - "timestamp": 282935.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Writer", - "visual": { - "x": 595, - "y": 263 - } - } - }, - "inputs": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [3], - "timestamp": 282936.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-5", - "type": "invoke", - "configuration": { - "$board": "#fn-5" - }, - "metadata": { - "title": "Prompt Extractor", - "visual": { - "x": 595, - "y": 71 - } - } - }, - "inputs": { - "$board": "#fn-5", - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - }, - "path": [4], - "timestamp": 282937.2999999821 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "http://localhost:5173/graphs/ad-writer-2.json#fn-5", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "fn-5-input", - "to": "fn-5-run", - "out": "*" - }, - { - "from": "fn-5-run", - "to": "fn-5-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-5-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-5-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true - } - }, - { - "id": "fn-5-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [4], - "timestamp": 282938.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-5-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [4, 1], - "timestamp": 282938.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-5-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - }, - "validatorMetadata": [], - "path": [4, 1], - "timestamp": 282939.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-5-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true - } - }, - "inputs": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true, - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - }, - "path": [4, 2], - "timestamp": 282939.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-5-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true - } - }, - "inputs": { - "code": "function fn_5({json}) {const{prompt}=json;return{prompt}}", - "name": "fn_5", - "raw": true, - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - }, - "outputs": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "validatorMetadata": [], - "path": [4, 2], - "timestamp": 282943.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-5-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "path": [4, 3], - "timestamp": 282943.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-5-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "path": [4, 3], - "timestamp": 282944.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [4], - "timestamp": 282944.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-5", - "type": "invoke", - "configuration": { - "$board": "#fn-5" - }, - "metadata": { - "title": "Prompt Extractor", - "visual": { - "x": 595, - "y": 71 - } - } - }, - "inputs": { - "$board": "#fn-5", - "json": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - }, - "outputs": { - "prompt": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "validatorMetadata": [], - "path": [4], - "timestamp": 282945.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-6", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - } - }, - "metadata": { - "title": "Customer", - "visual": { - "x": 820, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "path": [5], - "timestamp": 282945.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext" - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext" - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count" - } - } - }, - "path": [5], - "timestamp": 282946.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [5, 1], - "timestamp": 282946.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "validatorMetadata": [], - "path": [5, 1], - "timestamp": 282947.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [5, 2], - "timestamp": 282947.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [5, 2], - "timestamp": 282948.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - } - }, - "path": [5, 3], - "timestamp": 282948.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - } - }, - "outputs": { - "schemish": { - "requirements": [ - { - "requirement": "string, the requirement", - "justification": "string, reasoning behind including this requirement" - } - ] - } - }, - "validatorMetadata": [], - "path": [5, 3], - "timestamp": 282949.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "requirements": [ - { - "requirement": "string, the requirement", - "justification": "string, reasoning behind including this requirement" - } - ] - } - }, - "path": [5, 9], - "timestamp": 282950.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "requirements": [ - { - "requirement": "string, the requirement", - "justification": "string, reasoning behind including this requirement" - } - ] - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "validatorMetadata": [], - "path": [5, 9], - "timestamp": 282951.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "path": [5, 10], - "timestamp": 282951.5 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [5, 10], - "timestamp": 282952.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [5, 10, 1], - "timestamp": 282952.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "validatorMetadata": [], - "path": [5, 10, 1], - "timestamp": 282953.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "path": [5, 10, 2], - "timestamp": 282953.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [5, 10, 2], - "timestamp": 282956.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "path": [5, 10, 3], - "timestamp": 282957.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "path": [5, 10, 3], - "timestamp": 282957.6999999881 - } - }, - { - "type": "graphend", - "data": { - "path": [5, 10], - "timestamp": 282957.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [5, 10], - "timestamp": 282958.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [5, 11], - "timestamp": 282958.39999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [5, 11], - "timestamp": 282959.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [5, 11, 1], - "timestamp": 282959.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [5, 11, 1], - "timestamp": 282959.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [5, 11, 2], - "timestamp": 282960 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [5, 11, 2], - "timestamp": 282962.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [5, 11, 3], - "timestamp": 282963.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [5, 11, 3], - "timestamp": 282963.6999999881 - } - }, - { - "type": "graphend", - "data": { - "path": [5, 11], - "timestamp": 282963.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [5, 11], - "timestamp": 282964.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "path": [5, 14], - "timestamp": 282964.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [5, 14], - "timestamp": 282965.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [5, 14, 1], - "timestamp": 282966.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [5, 14, 1], - "timestamp": 282966.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [5, 14, 2], - "timestamp": 282966.7999999821 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 282967.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [5, 14, 2], - "timestamp": 282967.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [5, 14, 3], - "timestamp": 282968.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [5, 14, 3], - "timestamp": 282971.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [5, 14, 4], - "timestamp": 282971.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [5, 14, 4], - "timestamp": 282972.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [5, 14, 5], - "timestamp": 282972.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [5, 14, 5], - "timestamp": 282973.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - } - }, - "path": [5, 14, 6], - "timestamp": 282973.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [5, 14, 6], - "timestamp": 288193.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [5, 14, 11], - "timestamp": 288200.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```", - "context": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [5, 14, 11], - "timestamp": 288202.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - }, - "path": [5, 14, 13], - "timestamp": 288203.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - }, - "path": [5, 14, 13], - "timestamp": 288204.5 - } - }, - { - "type": "graphend", - "data": { - "path": [5, 14], - "timestamp": 288205 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - } - ], - "role": "model" - }, - "text": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - }, - "validatorMetadata": [], - "path": [5, 14], - "timestamp": 288205.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - }, - "json": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - }, - "path": [5, 16], - "timestamp": 288206.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - }, - "json": "```json\n{\n \"requirements\": [\n {\n \"requirement\": \"Clear and concise documentation\",\n \"justification\": \"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"\n },\n {\n \"requirement\": \"Real-world examples and case studies\",\n \"justification\": \"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"\n },\n {\n \"requirement\": \"A free trial or sandbox environment\",\n \"justification\": \"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"\n },\n {\n \"requirement\": \"Excellent customer support\",\n \"justification\": \"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"\n }\n ]\n}\n```" - }, - "outputs": { - "json": { - "requirements": [ - { - "requirement": "Clear and concise documentation", - "justification": "As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services." - }, - { - "requirement": "Real-world examples and case studies", - "justification": "I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects." - }, - { - "requirement": "A free trial or sandbox environment", - "justification": "I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs." - }, - { - "requirement": "Excellent customer support", - "justification": "I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential." - } - ] - } - }, - "validatorMetadata": [], - "path": [5, 16], - "timestamp": 288215 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "json": { - "requirements": [ - { - "requirement": "Clear and concise documentation", - "justification": "As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services." - }, - { - "requirement": "Real-world examples and case studies", - "justification": "I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects." - }, - { - "requirement": "A free trial or sandbox environment", - "justification": "I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs." - }, - { - "requirement": "Excellent customer support", - "justification": "I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential." - } - ] - } - }, - "path": [5, 19], - "timestamp": 288216.5 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [5, 19], - "timestamp": 288217.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [5, 19, 1], - "timestamp": 288218.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "json": { - "requirements": [ - { - "requirement": "Clear and concise documentation", - "justification": "As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services." - }, - { - "requirement": "Real-world examples and case studies", - "justification": "I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects." - }, - { - "requirement": "A free trial or sandbox environment", - "justification": "I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs." - }, - { - "requirement": "Excellent customer support", - "justification": "I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential." - } - ] - } - }, - "validatorMetadata": [], - "path": [5, 19, 1], - "timestamp": 288218.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "json": { - "requirements": [ - { - "requirement": "Clear and concise documentation", - "justification": "As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services." - }, - { - "requirement": "Real-world examples and case studies", - "justification": "I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects." - }, - { - "requirement": "A free trial or sandbox environment", - "justification": "I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs." - }, - { - "requirement": "Excellent customer support", - "justification": "I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential." - } - ] - } - }, - "path": [5, 19, 2], - "timestamp": 288219.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "json": { - "requirements": [ - { - "requirement": "Clear and concise documentation", - "justification": "As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services." - }, - { - "requirement": "Real-world examples and case studies", - "justification": "I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects." - }, - { - "requirement": "A free trial or sandbox environment", - "justification": "I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs." - }, - { - "requirement": "Excellent customer support", - "justification": "I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential." - } - ] - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ] - }, - "validatorMetadata": [], - "path": [5, 19, 2], - "timestamp": 288223.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ] - }, - "path": [5, 19, 3], - "timestamp": 288223.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ] - }, - "path": [5, 19, 3], - "timestamp": 288224.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [5, 19], - "timestamp": 288224.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - } - ], - "json": { - "requirements": [ - { - "requirement": "Clear and concise documentation", - "justification": "As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services." - }, - { - "requirement": "Real-world examples and case studies", - "justification": "I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects." - }, - { - "requirement": "A free trial or sandbox environment", - "justification": "I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs." - }, - { - "requirement": "Excellent customer support", - "justification": "I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential." - } - ] - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ] - }, - "validatorMetadata": [], - "path": [5, 19], - "timestamp": 288225.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "requirements": [ - { - "requirement": "Clear and concise documentation", - "justification": "As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services." - }, - { - "requirement": "Real-world examples and case studies", - "justification": "I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects." - }, - { - "requirement": "A free trial or sandbox environment", - "justification": "I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs." - }, - { - "requirement": "Excellent customer support", - "justification": "I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential." - } - ] - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ] - }, - "path": [5, 20], - "timestamp": 288225.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "requirements": [ - { - "requirement": "Clear and concise documentation", - "justification": "As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services." - }, - { - "requirement": "Real-world examples and case studies", - "justification": "I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects." - }, - { - "requirement": "A free trial or sandbox environment", - "justification": "I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs." - }, - { - "requirement": "Excellent customer support", - "justification": "I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential." - } - ] - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ] - }, - "path": [5, 20], - "timestamp": 288226.59999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [5], - "timestamp": 288227 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-6", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - } - }, - "metadata": { - "title": "Customer", - "visual": { - "x": 820, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "requirements": [ - { - "requirement": "Clear and concise documentation", - "justification": "As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services." - }, - { - "requirement": "Real-world examples and case studies", - "justification": "I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects." - }, - { - "requirement": "A free trial or sandbox environment", - "justification": "I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs." - }, - { - "requirement": "Excellent customer support", - "justification": "I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential." - } - ] - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ] - }, - "validatorMetadata": [], - "path": [5], - "timestamp": 288227.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-7", - "type": "structuredWorker", - "configuration": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Editor", - "visual": { - "x": 1045, - "y": 71 - } - } - }, - "inputs": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ] - }, - "path": [7], - "timestamp": 288229.09999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext" - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext" - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count" - } - } - }, - "path": [7], - "timestamp": 288230 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [7, 1], - "timestamp": 288230.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ] - }, - "validatorMetadata": [], - "path": [7, 1], - "timestamp": 288231.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [7, 2], - "timestamp": 288231.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [7, 2], - "timestamp": 288232.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "path": [7, 3], - "timestamp": 288232.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "outputs": { - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "validatorMetadata": [], - "path": [7, 3], - "timestamp": 288233.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "path": [7, 9], - "timestamp": 288235.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [7, 9], - "timestamp": 288236.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ], - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [7, 10], - "timestamp": 288236.39999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [7, 10], - "timestamp": 288237 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [7, 10, 1], - "timestamp": 288237.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ], - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [7, 10, 1], - "timestamp": 288237.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ], - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [7, 10, 2], - "timestamp": 288238 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ], - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [7, 10, 2], - "timestamp": 288242 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [7, 10, 3], - "timestamp": 288242.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [7, 10, 3], - "timestamp": 288243 - } - }, - { - "type": "graphend", - "data": { - "path": [7, 10], - "timestamp": 288243.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ], - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [7, 10], - "timestamp": 288243.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [7, 11], - "timestamp": 288244 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [7, 11], - "timestamp": 288245 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [7, 11, 1], - "timestamp": 288245.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [7, 11, 1], - "timestamp": 288245.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [7, 11, 2], - "timestamp": 288246.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [7, 11, 2], - "timestamp": 288249 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [7, 11, 3], - "timestamp": 288249.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [7, 11, 3], - "timestamp": 288249.7999999821 - } - }, - { - "type": "graphend", - "data": { - "path": [7, 11], - "timestamp": 288250.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [7, 11], - "timestamp": 288250.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [7, 14], - "timestamp": 288251.2999999821 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [7, 14], - "timestamp": 288252.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [7, 14, 1], - "timestamp": 288252.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [7, 14, 1], - "timestamp": 288253.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [7, 14, 2], - "timestamp": 288253.5 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 288253.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [7, 14, 2], - "timestamp": 288254.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [7, 14, 3], - "timestamp": 288255.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [7, 14, 3], - "timestamp": 288258.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [7, 14, 4], - "timestamp": 288258.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [7, 14, 4], - "timestamp": 288259.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [7, 14, 5], - "timestamp": 288259.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [7, 14, 5], - "timestamp": 288260.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "path": [7, 14, 6], - "timestamp": 288260.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [7, 14, 6], - "timestamp": 293614.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [7, 14, 11], - "timestamp": 293622.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}", - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [7, 14, 11], - "timestamp": 293624.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - }, - "path": [7, 14, 13], - "timestamp": 293625.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - }, - "path": [7, 14, 13], - "timestamp": 293626.09999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [7, 14], - "timestamp": 293626.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - }, - "validatorMetadata": [], - "path": [7, 14], - "timestamp": 293627.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - }, - "path": [7, 16], - "timestamp": 293628.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "validatorMetadata": [], - "path": [7, 16], - "timestamp": 293640.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "path": [7, 19], - "timestamp": 293642.39999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [7, 19], - "timestamp": 293643.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [7, 19, 1], - "timestamp": 293644.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "validatorMetadata": [], - "path": [7, 19, 1], - "timestamp": 293644.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "path": [7, 19, 2], - "timestamp": 293645.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [7, 19, 2], - "timestamp": 293649.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [7, 19, 3], - "timestamp": 293650 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [7, 19, 3], - "timestamp": 293650.59999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [7, 19], - "timestamp": 293651 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [7, 19], - "timestamp": 293651.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [7, 20], - "timestamp": 293651.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [7, 20], - "timestamp": 293652.6999999881 - } - }, - { - "type": "graphend", - "data": { - "path": [7], - "timestamp": 293653 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-7", - "type": "structuredWorker", - "configuration": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Editor", - "visual": { - "x": 1045, - "y": 71 - } - } - }, - "inputs": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Developers, Revolutionize AI with Breadboard!", - "Unlock the Power of AI with Breadboard's Playground", - "Prototype AI Solutions in a Flash with Breadboard", - "Integrate AI Seamlessly with Breadboard and Gemini APIs", - "Empower Your Projects with Breadboard's Accessible AI", - "Visualize AI Insights with Breadboard's Graph Creation", - "Breadboard: Where Developers and AI Unite", - "Play, Experiment, and Innovate with Breadboard's AI Toolkit", - "Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform", - "Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools", - "Developers, Supercharge Your Projects with Breadboard's AI Engine", - "Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation", - "Prototype and Iterate Rapidly with Breadboard's Agile AI Framework", - "Integrate AI into Your Projects with Breadboard's Comprehensive APIs", - "Breadboard: Empowering Developers to Build the Future of AI" - ], - "descriptions": [ - "Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.", - "Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.", - "Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.", - "Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [7], - "timestamp": 293653.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "repeater-8", - "type": "repeater", - "configuration": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4 - }, - "metadata": { - "title": "Ad refinery", - "visual": { - "x": 1250, - "y": 71 - } - } - }, - "inputs": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [8], - "timestamp": 293654.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=repeater", - "title": "Repeater", - "description": "A worker whose job it is to repeat the same thing over and over, until some condition is met or the max count of repetitions is reached.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "counter", - "to": "invokeAgent", - "out": "continue", - "in": "context" - }, - { - "from": "counter", - "to": "counter", - "out": "count", - "in": "count" - }, - { - "from": "counter", - "to": "output-2", - "out": "stop", - "in": "context" - }, - { - "from": "invokeAgent", - "to": "exit", - "out": "exit", - "in": "context" - }, - { - "from": "invokeAgent", - "to": "counter", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "invokeAgent", - "out": "worker", - "in": "$board", - "constant": true - }, - { - "from": "input-1", - "to": "invokeAgent", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "counter", - "out": "max", - "in": "count" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "worker": { - "title": "Worker", - "behavior": ["board"], - "description": "Worker to repeat", - "type": "object" - }, - "context": { - "title": "Context", - "type": "array", - "format": "multiline", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "description": "Initial conversation context" - }, - "max": { - "title": "Max", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "type": "number", - "default": "-1", - "examples": ["3"] - } - }, - "required": ["worker"] - } - } - }, - { - "id": "exit", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Exit", - "description": "Exiting early from the repeater" - } - } - ], - "kits": [], - "graphs": { - "counter": { - "edges": [ - { - "from": "counter-input", - "to": "counter-run", - "out": "*" - }, - { - "from": "counter-run", - "to": "counter-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - { - "id": "counter-output", - "type": "output", - "configuration": {} - } - ] - } - } - }, - "path": [8], - "timestamp": 293656.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "worker": { - "title": "Worker", - "behavior": ["board"], - "description": "Worker to repeat", - "type": "object" - }, - "context": { - "title": "Context", - "type": "array", - "format": "multiline", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "description": "Initial conversation context" - }, - "max": { - "title": "Max", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "type": "number", - "default": "-1", - "examples": ["3"] - } - }, - "required": ["worker"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "worker": { - "title": "Worker", - "behavior": ["board"], - "description": "Worker to repeat", - "type": "object" - }, - "context": { - "title": "Context", - "type": "array", - "format": "multiline", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "description": "Initial conversation context" - }, - "max": { - "title": "Max", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "type": "number", - "default": "-1", - "examples": ["3"] - } - }, - "required": ["worker"] - } - }, - "path": [8, 1], - "timestamp": 293656.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "worker": { - "title": "Worker", - "behavior": ["board"], - "description": "Worker to repeat", - "type": "object" - }, - "context": { - "title": "Context", - "type": "array", - "format": "multiline", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "description": "Initial conversation context" - }, - "max": { - "title": "Max", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "type": "number", - "default": "-1", - "examples": ["3"] - } - }, - "required": ["worker"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "worker": { - "title": "Worker", - "behavior": ["board"], - "description": "Worker to repeat", - "type": "object" - }, - "context": { - "title": "Context", - "type": "array", - "format": "multiline", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "description": "Initial conversation context" - }, - "max": { - "title": "Max", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "type": "number", - "default": "-1", - "examples": ["3"] - } - }, - "required": ["worker"] - } - }, - "outputs": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 1], - "timestamp": 293657.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [8, 2], - "timestamp": 293657.6999999881 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "kits": [], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - }, - "path": [8, 2], - "timestamp": 293658.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "path": [8, 2, 1], - "timestamp": 293659.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 1], - "timestamp": 293659.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [8, 2, 2], - "timestamp": 293660.1999999881 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 2, 2], - "timestamp": 293660.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 2, 2, 1], - "timestamp": 293661.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 2, 1], - "timestamp": 293661.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "path": [8, 2, 2, 2], - "timestamp": 293662.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 2, 2, 2], - "timestamp": 293665.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - "path": [8, 2, 2, 3], - "timestamp": 293666.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - "path": [8, 2, 2, 3], - "timestamp": 293667.1999999881 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 2], - "timestamp": 293667.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 2, 2], - "timestamp": 293668 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - "path": [8, 2, 3], - "timestamp": 293668.2999999821 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext" - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext" - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count" - } - } - }, - "path": [8, 2, 3], - "timestamp": 293669 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [8, 2, 3, 1], - "timestamp": 293669.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 2, 3, 1], - "timestamp": 293669.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [8, 2, 3, 2], - "timestamp": 293670.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 2], - "timestamp": 293670.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "path": [8, 2, 3, 3], - "timestamp": 293671.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "outputs": { - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 3], - "timestamp": 293671.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "path": [8, 2, 3, 9], - "timestamp": 293674.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 9], - "timestamp": 293674.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [8, 2, 3, 10], - "timestamp": 293675.09999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 2, 3, 10], - "timestamp": 293675.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 2, 3, 10, 1], - "timestamp": 293676.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 10, 1], - "timestamp": 293676.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [8, 2, 3, 10, 2], - "timestamp": 293676.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 3, 10, 2], - "timestamp": 293680.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 2, 3, 10, 3], - "timestamp": 293680.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 2, 3, 10, 3], - "timestamp": 293681.1999999881 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 3, 10], - "timestamp": 293681.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 3, 10], - "timestamp": 293681.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [8, 2, 3, 11], - "timestamp": 293682.2999999821 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 2, 3, 11], - "timestamp": 293682.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 2, 3, 11, 1], - "timestamp": 293683.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 11, 1], - "timestamp": 293683.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [8, 2, 3, 11, 2], - "timestamp": 293684.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [8, 2, 3, 11, 2], - "timestamp": 293687.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [8, 2, 3, 11, 3], - "timestamp": 293688 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [8, 2, 3, 11, 3], - "timestamp": 293688.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 3, 11], - "timestamp": 293688.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [8, 2, 3, 11], - "timestamp": 293689.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 2, 3, 14], - "timestamp": 293690.09999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [8, 2, 3, 14], - "timestamp": 293690.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [8, 2, 3, 14, 1], - "timestamp": 293691.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 1], - "timestamp": 293691.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [8, 2, 3, 14, 2], - "timestamp": 293692.1999999881 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 293692.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 2], - "timestamp": 293693.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [8, 2, 3, 14, 3], - "timestamp": 293694.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 3], - "timestamp": 293697.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [8, 2, 3, 14, 4], - "timestamp": 293698 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 4], - "timestamp": 293698.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [8, 2, 3, 14, 5], - "timestamp": 293698.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 5], - "timestamp": 293699.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "path": [8, 2, 3, 14, 6], - "timestamp": 293699.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 6], - "timestamp": 297829.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [8, 2, 3, 14, 11], - "timestamp": 297838.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}", - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14, 11], - "timestamp": 297840.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - }, - "path": [8, 2, 3, 14, 13], - "timestamp": 297842.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - }, - "path": [8, 2, 3, 14, 13], - "timestamp": 297843 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 3, 14], - "timestamp": 297843.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - }, - "validatorMetadata": [], - "path": [8, 2, 3, 14], - "timestamp": 297844.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - }, - "path": [8, 2, 3, 16], - "timestamp": 297845.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Unlock AI's Power with Breadboard", - "Prototype AI with Breadboard", - "Integrate AI with Breadboard & Gemini", - "Empower Projects with Breadboard AI", - "Visualize AI with Breadboard", - "Breadboard: Developers & AI", - "Play & Innovate with Breadboard AI", - "Accelerate AI with Breadboard", - "Unlock AI with Breadboard", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: AI for Developers" - ], - "descriptions": [ - "Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.", - "Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.", - "Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.", - "Breadboard: Empowering developers to build the future of AI with our developer-friendly platform." - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 16], - "timestamp": 297855.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Unlock AI's Power with Breadboard", - "Prototype AI with Breadboard", - "Integrate AI with Breadboard & Gemini", - "Empower Projects with Breadboard AI", - "Visualize AI with Breadboard", - "Breadboard: Developers & AI", - "Play & Innovate with Breadboard AI", - "Accelerate AI with Breadboard", - "Unlock AI with Breadboard", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: AI for Developers" - ], - "descriptions": [ - "Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.", - "Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.", - "Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.", - "Breadboard: Empowering developers to build the future of AI with our developer-friendly platform." - ] - } - } - }, - "path": [8, 2, 3, 19], - "timestamp": 297857.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 2, 3, 19], - "timestamp": 297859 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 2, 3, 19, 1], - "timestamp": 297859.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Unlock AI's Power with Breadboard", - "Prototype AI with Breadboard", - "Integrate AI with Breadboard & Gemini", - "Empower Projects with Breadboard AI", - "Visualize AI with Breadboard", - "Breadboard: Developers & AI", - "Play & Innovate with Breadboard AI", - "Accelerate AI with Breadboard", - "Unlock AI with Breadboard", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: AI for Developers" - ], - "descriptions": [ - "Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.", - "Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.", - "Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.", - "Breadboard: Empowering developers to build the future of AI with our developer-friendly platform." - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 2, 3, 19, 1], - "timestamp": 297860.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Unlock AI's Power with Breadboard", - "Prototype AI with Breadboard", - "Integrate AI with Breadboard & Gemini", - "Empower Projects with Breadboard AI", - "Visualize AI with Breadboard", - "Breadboard: Developers & AI", - "Play & Innovate with Breadboard AI", - "Accelerate AI with Breadboard", - "Unlock AI with Breadboard", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: AI for Developers" - ], - "descriptions": [ - "Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.", - "Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.", - "Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.", - "Breadboard: Empowering developers to build the future of AI with our developer-friendly platform." - ] - } - } - }, - "path": [8, 2, 3, 19, 2], - "timestamp": 297860.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Unlock AI's Power with Breadboard", - "Prototype AI with Breadboard", - "Integrate AI with Breadboard & Gemini", - "Empower Projects with Breadboard AI", - "Visualize AI with Breadboard", - "Breadboard: Developers & AI", - "Play & Innovate with Breadboard AI", - "Accelerate AI with Breadboard", - "Unlock AI with Breadboard", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: AI for Developers" - ], - "descriptions": [ - "Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.", - "Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.", - "Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.", - "Breadboard: Empowering developers to build the future of AI with our developer-friendly platform." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 3, 19, 2], - "timestamp": 297864.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "path": [8, 2, 3, 19, 3], - "timestamp": 297865.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "path": [8, 2, 3, 19, 3], - "timestamp": 297866.5 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 3, 19], - "timestamp": 297867 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Unlock AI's Power with Breadboard", - "Prototype AI with Breadboard", - "Integrate AI with Breadboard & Gemini", - "Empower Projects with Breadboard AI", - "Visualize AI with Breadboard", - "Breadboard: Developers & AI", - "Play & Innovate with Breadboard AI", - "Accelerate AI with Breadboard", - "Unlock AI with Breadboard", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: AI for Developers" - ], - "descriptions": [ - "Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.", - "Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.", - "Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.", - "Breadboard: Empowering developers to build the future of AI with our developer-friendly platform." - ] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 3, 19], - "timestamp": 297867.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Unlock AI's Power with Breadboard", - "Prototype AI with Breadboard", - "Integrate AI with Breadboard & Gemini", - "Empower Projects with Breadboard AI", - "Visualize AI with Breadboard", - "Breadboard: Developers & AI", - "Play & Innovate with Breadboard AI", - "Accelerate AI with Breadboard", - "Unlock AI with Breadboard", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: AI for Developers" - ], - "descriptions": [ - "Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.", - "Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.", - "Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.", - "Breadboard: Empowering developers to build the future of AI with our developer-friendly platform." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "path": [8, 2, 3, 20], - "timestamp": 297868 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Unlock AI's Power with Breadboard", - "Prototype AI with Breadboard", - "Integrate AI with Breadboard & Gemini", - "Empower Projects with Breadboard AI", - "Visualize AI with Breadboard", - "Breadboard: Developers & AI", - "Play & Innovate with Breadboard AI", - "Accelerate AI with Breadboard", - "Unlock AI with Breadboard", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: AI for Developers" - ], - "descriptions": [ - "Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.", - "Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.", - "Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.", - "Breadboard: Empowering developers to build the future of AI with our developer-friendly platform." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "path": [8, 2, 3, 20], - "timestamp": 297868.7999999821 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2, 3], - "timestamp": 297869.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Unlock AI's Power with Breadboard", - "Prototype AI with Breadboard", - "Integrate AI with Breadboard & Gemini", - "Empower Projects with Breadboard AI", - "Visualize AI with Breadboard", - "Breadboard: Developers & AI", - "Play & Innovate with Breadboard AI", - "Accelerate AI with Breadboard", - "Unlock AI with Breadboard", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: AI for Developers" - ], - "descriptions": [ - "Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.", - "Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.", - "Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.", - "Breadboard: Empowering developers to build the future of AI with our developer-friendly platform." - ] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2, 3], - "timestamp": 297869.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "path": [8, 2, 6], - "timestamp": 297871.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "path": [8, 2, 6], - "timestamp": 297871.59999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 2], - "timestamp": 297872.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 2], - "timestamp": 297872.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - "inputs": { - "$board": "#counter", - "count": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "path": [8, 4], - "timestamp": 297873.59999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=repeater#counter", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "counter-input", - "to": "counter-run", - "out": "*" - }, - { - "from": "counter-run", - "to": "counter-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - { - "id": "counter-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 4], - "timestamp": 297874.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 4, 1], - "timestamp": 297875.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "count": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 4, 1], - "timestamp": 297875.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - "inputs": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true, - "count": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "path": [8, 4, 2], - "timestamp": 297876.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - "inputs": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true, - "count": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "count": 3 - }, - "validatorMetadata": [], - "path": [8, 4, 2], - "timestamp": 297880.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "count": 3 - }, - "path": [8, 4, 3], - "timestamp": 297881.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "count": 3 - }, - "path": [8, 4, 3], - "timestamp": 297881.89999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 4], - "timestamp": 297882.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - "inputs": { - "$board": "#counter", - "count": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "count": 3 - }, - "validatorMetadata": [], - "path": [8, 4], - "timestamp": 297882.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "path": [8, 7], - "timestamp": 297884.09999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "kits": [], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - }, - "path": [8, 7], - "timestamp": 297885.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "path": [8, 7, 1], - "timestamp": 297885.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 7, 1], - "timestamp": 297886.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "path": [8, 7, 2], - "timestamp": 297886.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 7, 2], - "timestamp": 297887.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 7, 2, 1], - "timestamp": 297888 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 7, 2, 1], - "timestamp": 297888.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "path": [8, 7, 2, 2], - "timestamp": 297889 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 7, 2, 2], - "timestamp": 297892.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - "path": [8, 7, 2, 3], - "timestamp": 297893.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - "path": [8, 7, 2, 3], - "timestamp": 297893.7999999821 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 7, 2], - "timestamp": 297894.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 7, 2], - "timestamp": 297894.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - "path": [8, 7, 3], - "timestamp": 297895 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext" - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext" - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count" - } - } - }, - "path": [8, 7, 3], - "timestamp": 297895.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [8, 7, 3, 1], - "timestamp": 297896.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 7, 3, 1], - "timestamp": 297896.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [8, 7, 3, 2], - "timestamp": 297897.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [8, 7, 3, 2], - "timestamp": 297897.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "path": [8, 7, 3, 3], - "timestamp": 297898.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "outputs": { - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 7, 3, 3], - "timestamp": 297899.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "path": [8, 7, 3, 9], - "timestamp": 297901.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [8, 7, 3, 9], - "timestamp": 297902.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [8, 7, 3, 10], - "timestamp": 297902.7999999821 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 7, 3, 10], - "timestamp": 297903.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 7, 3, 10, 1], - "timestamp": 297903.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [8, 7, 3, 10, 1], - "timestamp": 297904.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [8, 7, 3, 10, 2], - "timestamp": 297904.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [8, 7, 3, 10, 2], - "timestamp": 297908.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 7, 3, 10, 3], - "timestamp": 297908.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 7, 3, 10, 3], - "timestamp": 297909.2999999821 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 7, 3, 10], - "timestamp": 297909.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [8, 7, 3, 10], - "timestamp": 297910 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [8, 7, 3, 11], - "timestamp": 297910.5 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 7, 3, 11], - "timestamp": 297911.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 7, 3, 11, 1], - "timestamp": 297911.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [8, 7, 3, 11, 1], - "timestamp": 297912.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [8, 7, 3, 11, 2], - "timestamp": 297912.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [8, 7, 3, 11, 2], - "timestamp": 297916.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [8, 7, 3, 11, 3], - "timestamp": 297916.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [8, 7, 3, 11, 3], - "timestamp": 297917.6999999881 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 7, 3, 11], - "timestamp": 297918.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [8, 7, 3, 11], - "timestamp": 297918.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 7, 3, 14], - "timestamp": 297920.2999999821 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [8, 7, 3, 14], - "timestamp": 297921.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [8, 7, 3, 14, 1], - "timestamp": 297921.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [8, 7, 3, 14, 1], - "timestamp": 297922.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [8, 7, 3, 14, 2], - "timestamp": 297923.09999999404 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 297923.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [8, 7, 3, 14, 2], - "timestamp": 297924.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [8, 7, 3, 14, 3], - "timestamp": 297926.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [8, 7, 3, 14, 3], - "timestamp": 297932.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [8, 7, 3, 14, 4], - "timestamp": 297933.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [8, 7, 3, 14, 4], - "timestamp": 297934.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [8, 7, 3, 14, 5], - "timestamp": 297934.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [8, 7, 3, 14, 5], - "timestamp": 297935.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "path": [8, 7, 3, 14, 6], - "timestamp": 297935.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 7, 3, 14, 6], - "timestamp": 301090.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [8, 7, 3, 14, 11], - "timestamp": 301099.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}", - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [8, 7, 3, 14, 11], - "timestamp": 301101.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - }, - "path": [8, 7, 3, 14, 13], - "timestamp": 301103.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - }, - "path": [8, 7, 3, 14, 13], - "timestamp": 301104.2999999821 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 7, 3, 14], - "timestamp": 301105.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - }, - "validatorMetadata": [], - "path": [8, 7, 3, 14], - "timestamp": 301106 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - }, - "path": [8, 7, 3, 16], - "timestamp": 301107.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard!", - "Unlock AI's Power!", - "Integrate AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, and integrate AI with ease.", - "Breadboard: Accessible AI for developers.", - "Breadboard: Accelerate your AI journey.", - "Breadboard: Empowering developers to build the future of AI." - ], - "descriptions": [] - } - } - }, - "validatorMetadata": [], - "path": [8, 7, 3, 16], - "timestamp": 301116.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard!", - "Unlock AI's Power!", - "Integrate AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, and integrate AI with ease.", - "Breadboard: Accessible AI for developers.", - "Breadboard: Accelerate your AI journey.", - "Breadboard: Empowering developers to build the future of AI." - ], - "descriptions": [] - } - } - }, - "path": [8, 7, 3, 19], - "timestamp": 301118.59999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 7, 3, 19], - "timestamp": 301119.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 7, 3, 19, 1], - "timestamp": 301120.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard!", - "Unlock AI's Power!", - "Integrate AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, and integrate AI with ease.", - "Breadboard: Accessible AI for developers.", - "Breadboard: Accelerate your AI journey.", - "Breadboard: Empowering developers to build the future of AI." - ], - "descriptions": [] - } - } - }, - "validatorMetadata": [], - "path": [8, 7, 3, 19, 1], - "timestamp": 301121.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard!", - "Unlock AI's Power!", - "Integrate AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, and integrate AI with ease.", - "Breadboard: Accessible AI for developers.", - "Breadboard: Accelerate your AI journey.", - "Breadboard: Empowering developers to build the future of AI." - ], - "descriptions": [] - } - } - }, - "path": [8, 7, 3, 19, 2], - "timestamp": 301121.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard!", - "Unlock AI's Power!", - "Integrate AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, and integrate AI with ease.", - "Breadboard: Accessible AI for developers.", - "Breadboard: Accelerate your AI journey.", - "Breadboard: Empowering developers to build the future of AI." - ], - "descriptions": [] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 7, 3, 19, 2], - "timestamp": 301126.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 7, 3, 19, 3], - "timestamp": 301127 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 7, 3, 19, 3], - "timestamp": 301127.7999999821 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 7, 3, 19], - "timestamp": 301128.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard!", - "Unlock AI's Power!", - "Integrate AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, and integrate AI with ease.", - "Breadboard: Accessible AI for developers.", - "Breadboard: Accelerate your AI journey.", - "Breadboard: Empowering developers to build the future of AI." - ], - "descriptions": [] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 7, 3, 19], - "timestamp": 301129 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard!", - "Unlock AI's Power!", - "Integrate AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, and integrate AI with ease.", - "Breadboard: Accessible AI for developers.", - "Breadboard: Accelerate your AI journey.", - "Breadboard: Empowering developers to build the future of AI." - ], - "descriptions": [] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 7, 3, 20], - "timestamp": 301129.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard!", - "Unlock AI's Power!", - "Integrate AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, and integrate AI with ease.", - "Breadboard: Accessible AI for developers.", - "Breadboard: Accelerate your AI journey.", - "Breadboard: Empowering developers to build the future of AI." - ], - "descriptions": [] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 7, 3, 20], - "timestamp": 301130.2999999821 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 7, 3], - "timestamp": 301130.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard!", - "Unlock AI's Power!", - "Integrate AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, and integrate AI with ease.", - "Breadboard: Accessible AI for developers.", - "Breadboard: Accelerate your AI journey.", - "Breadboard: Empowering developers to build the future of AI." - ], - "descriptions": [] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 7, 3], - "timestamp": 301131.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 7, 6], - "timestamp": 301132.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 7, 6], - "timestamp": 301133.59999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 7], - "timestamp": 301134.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 7], - "timestamp": 301134.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - "inputs": { - "$board": "#counter", - "count": 3, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 8], - "timestamp": 301135.1999999881 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=repeater#counter", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "counter-input", - "to": "counter-run", - "out": "*" - }, - { - "from": "counter-run", - "to": "counter-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - { - "id": "counter-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 8], - "timestamp": 301136.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 8, 1], - "timestamp": 301137.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "count": 3, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 8, 1], - "timestamp": 301137.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - "inputs": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true, - "count": 3, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 8, 2], - "timestamp": 301138.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - "inputs": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true, - "count": 3, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "count": 2 - }, - "validatorMetadata": [], - "path": [8, 8, 2], - "timestamp": 301142.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "count": 2 - }, - "path": [8, 8, 3], - "timestamp": 301143.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "count": 2 - }, - "path": [8, 8, 3], - "timestamp": 301144.09999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 8], - "timestamp": 301144.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - "inputs": { - "$board": "#counter", - "count": 3, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "count": 2 - }, - "validatorMetadata": [], - "path": [8, 8], - "timestamp": 301145 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 12], - "timestamp": 301147 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "kits": [], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - }, - "path": [8, 12], - "timestamp": 301148.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "path": [8, 12, 1], - "timestamp": 301148.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 12, 1], - "timestamp": 301149.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 12, 2], - "timestamp": 301150 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 12, 2], - "timestamp": 301150.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 12, 2, 1], - "timestamp": 301151.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 12, 2, 1], - "timestamp": 301152 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 12, 2, 2], - "timestamp": 301152.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 12, 2, 2], - "timestamp": 301156.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - "path": [8, 12, 2, 3], - "timestamp": 301156.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - "path": [8, 12, 2, 3], - "timestamp": 301157.59999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 12, 2], - "timestamp": 301158.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 12, 2], - "timestamp": 301158.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - "path": [8, 12, 3], - "timestamp": 301159 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext" - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext" - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count" - } - } - }, - "path": [8, 12, 3], - "timestamp": 301159.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [8, 12, 3, 1], - "timestamp": 301160.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 12, 3, 1], - "timestamp": 301161.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [8, 12, 3, 2], - "timestamp": 301161.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [8, 12, 3, 2], - "timestamp": 301162.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "path": [8, 12, 3, 3], - "timestamp": 301163.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "outputs": { - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 12, 3, 3], - "timestamp": 301163.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "path": [8, 12, 3, 9], - "timestamp": 301166.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [8, 12, 3, 9], - "timestamp": 301167 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [8, 12, 3, 10], - "timestamp": 301167.5 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 12, 3, 10], - "timestamp": 301168.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 12, 3, 10, 1], - "timestamp": 301168.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [8, 12, 3, 10, 1], - "timestamp": 301169.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [8, 12, 3, 10, 2], - "timestamp": 301169.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [8, 12, 3, 10, 2], - "timestamp": 301174.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 12, 3, 10, 3], - "timestamp": 301175.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 12, 3, 10, 3], - "timestamp": 301176.1999999881 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 12, 3, 10], - "timestamp": 301176.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [8, 12, 3, 10], - "timestamp": 301177.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [8, 12, 3, 11], - "timestamp": 301178 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 12, 3, 11], - "timestamp": 301179 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 12, 3, 11, 1], - "timestamp": 301179.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [8, 12, 3, 11, 1], - "timestamp": 301180.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [8, 12, 3, 11, 2], - "timestamp": 301180.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [8, 12, 3, 11, 2], - "timestamp": 301186.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [8, 12, 3, 11, 3], - "timestamp": 301187.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [8, 12, 3, 11, 3], - "timestamp": 301187.7999999821 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 12, 3, 11], - "timestamp": 301188.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [8, 12, 3, 11], - "timestamp": 301188.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 12, 3, 14], - "timestamp": 301189.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [8, 12, 3, 14], - "timestamp": 301190.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [8, 12, 3, 14, 1], - "timestamp": 301191.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [8, 12, 3, 14, 1], - "timestamp": 301191.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [8, 12, 3, 14, 2], - "timestamp": 301192.5 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 301193 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [8, 12, 3, 14, 2], - "timestamp": 301194 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [8, 12, 3, 14, 3], - "timestamp": 301195.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [8, 12, 3, 14, 3], - "timestamp": 301199 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [8, 12, 3, 14, 4], - "timestamp": 301199.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [8, 12, 3, 14, 4], - "timestamp": 301200.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [8, 12, 3, 14, 5], - "timestamp": 301200.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [8, 12, 3, 14, 5], - "timestamp": 301201.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "path": [8, 12, 3, 14, 6], - "timestamp": 301202 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 12, 3, 14, 6], - "timestamp": 303796.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [8, 12, 3, 14, 11], - "timestamp": 303807.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}", - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [8, 12, 3, 14, 11], - "timestamp": 303809.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - }, - "path": [8, 12, 3, 14, 13], - "timestamp": 303811.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - }, - "path": [8, 12, 3, 14, 13], - "timestamp": 303812.6999999881 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 12, 3, 14], - "timestamp": 303813.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - }, - "validatorMetadata": [], - "path": [8, 12, 3, 14], - "timestamp": 303814.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - }, - "path": [8, 12, 3, 16], - "timestamp": 303816.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "validatorMetadata": [], - "path": [8, 12, 3, 16], - "timestamp": 303825.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "path": [8, 12, 3, 19], - "timestamp": 303828.09999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 12, 3, 19], - "timestamp": 303829.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 12, 3, 19, 1], - "timestamp": 303830.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "validatorMetadata": [], - "path": [8, 12, 3, 19, 1], - "timestamp": 303831.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "path": [8, 12, 3, 19, 2], - "timestamp": 303832.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 12, 3, 19, 2], - "timestamp": 303837.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 12, 3, 19, 3], - "timestamp": 303838.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 12, 3, 19, 3], - "timestamp": 303839.09999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 12, 3, 19], - "timestamp": 303839.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 12, 3, 19], - "timestamp": 303840.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 12, 3, 20], - "timestamp": 303841 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 12, 3, 20], - "timestamp": 303841.7999999821 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 12, 3], - "timestamp": 303842.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 12, 3], - "timestamp": 303843 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 12, 6], - "timestamp": 303844.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 12, 6], - "timestamp": 303845.5 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 12], - "timestamp": 303846.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 12], - "timestamp": 303846.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - "inputs": { - "$board": "#counter", - "count": 2, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 13], - "timestamp": 303847.2999999821 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=repeater#counter", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "counter-input", - "to": "counter-run", - "out": "*" - }, - { - "from": "counter-run", - "to": "counter-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - { - "id": "counter-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 13], - "timestamp": 303848.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 13, 1], - "timestamp": 303849.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "count": 2, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 13, 1], - "timestamp": 303850 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - "inputs": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true, - "count": 2, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 13, 2], - "timestamp": 303850.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - "inputs": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true, - "count": 2, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "count": 1 - }, - "validatorMetadata": [], - "path": [8, 13, 2], - "timestamp": 303855.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "count": 1 - }, - "path": [8, 13, 3], - "timestamp": 303856.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "count": 1 - }, - "path": [8, 13, 3], - "timestamp": 303857.1999999881 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 13], - "timestamp": 303857.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - "inputs": { - "$board": "#counter", - "count": 2, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "count": 1 - }, - "validatorMetadata": [], - "path": [8, 13], - "timestamp": 303858.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 17], - "timestamp": 303861.39999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "kits": [], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - }, - "path": [8, 17], - "timestamp": 303863 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "path": [8, 17, 1], - "timestamp": 303863.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 17, 1], - "timestamp": 303864.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 17, 2], - "timestamp": 303865.2999999821 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 17, 2], - "timestamp": 303866.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 17, 2, 1], - "timestamp": 303866.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 17, 2, 1], - "timestamp": 303867.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 17, 2, 2], - "timestamp": 303868.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - "inputs": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 17, 2, 2], - "timestamp": 303875 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - "path": [8, 17, 2, 3], - "timestamp": 303875.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - "path": [8, 17, 2, 3], - "timestamp": 303876.59999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 17, 2], - "timestamp": 303877.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - "inputs": { - "$board": "#fn-3", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "warning": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 17, 2], - "timestamp": 303877.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - "path": [8, 17, 3], - "timestamp": 303878.1999999881 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker", - "title": "Structured Worker", - "description": "A worker who outputs structure data (JSON) provided a schema.", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.1", - "edges": [ - { - "from": "assembleContext", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "validate", - "to": "count", - "out": "$error", - "in": "error" - }, - { - "from": "validate", - "to": "errorOutput", - "out": "$error", - "in": "$error" - }, - { - "from": "validate", - "to": "assembleContext", - "out": "json", - "in": "json" - }, - { - "from": "validate", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "buildContext", - "to": "count", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "buildContext", - "to": "assembleContext", - "out": "context", - "in": "context" - }, - { - "from": "generate", - "to": "validate", - "out": "text", - "in": "json" - }, - { - "from": "input-1", - "to": "schemish", - "out": "schema", - "in": "schema" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "buildContext", - "out": "instruction", - "in": "instruction" - }, - { - "from": "input-1", - "to": "validate", - "out": "schema", - "in": "schema", - "constant": true - }, - { - "from": "count", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "count", - "to": "generate", - "out": "continue", - "in": "context" - }, - { - "from": "count", - "to": "errorOutput", - "out": "stop", - "in": "context" - }, - { - "from": "format", - "to": "buildContext", - "out": "prompt", - "in": "format" - }, - { - "from": "schemish", - "to": "format", - "out": "schemish", - "in": "schemish" - }, - { - "from": "initialValues", - "to": "count", - "out": "count", - "in": "count" - }, - { - "from": "initialValues", - "to": "count", - "out": "error", - "in": "error" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - { - "id": "errorOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "$error": { - "title": "$error", - "description": "The error if the JSON is invalid.", - "type": "object", - "properties": { - "kind": { - "type": "string", - "enum": ["error"] - }, - "error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": ["parsing", "validation"] - }, - "message": { - "type": "string" - } - } - } - } - }, - "context": { - "type": "string", - "title": "context" - } - } - } - }, - "metadata": { - "title": "Error Output", - "description": "Displaying error output, giving up on JSON healing" - } - }, - { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - } - ], - "kits": [], - "graphs": { - "assembleContext": { - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext" - }, - "buildContext": { - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext" - }, - "count": { - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count" - } - } - }, - "path": [8, 17, 3], - "timestamp": 303879 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "path": [8, 17, 3, 1], - "timestamp": 303879.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "schema": { - "title": "Schema", - "description": "The schema to convert to schemish.", - "type": "object", - "examples": [ - "{\n \"type\": \"object\",\n \"properties\": {\n \"poems\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"inspiration\": {\n \"type\": \"string\",\n \"description\": \"The inspiration behind the poem\"\n },\n \"poem\": {\n \"type\": \"string\",\n \"description\": \"The poem itself\"\n }\n }\n }\n }\n }\n}" - ], - "behavior": ["json-schema"], - "default": "{}" - }, - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - }, - "instruction": { - "title": "Instruction", - "format": "multiline", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up three two-line rhyming poems about it.\nLook at the topic below and do your magic" - ], - "type": "string" - } - }, - "required": ["instruction"] - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - "validatorMetadata": [], - "path": [8, 17, 3, 1], - "timestamp": 303880.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "path": [8, 17, 3, 2], - "timestamp": 303880.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "initialValues", - "type": "passthrough", - "configuration": { - "count": 5, - "error": "stub" - }, - "metadata": { - "title": "Initial Values", - "description": "Populating initial values for the counter" - } - }, - "inputs": { - "count": 5, - "error": "stub" - }, - "outputs": { - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [8, 17, 3, 2], - "timestamp": 303881.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "path": [8, 17, 3, 3], - "timestamp": 303881.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "schemish", - "type": "schemish", - "configuration": {}, - "metadata": { - "title": "Schemish", - "description": "Converting JSON schema to a more compact format" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "outputs": { - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 17, 3, 3], - "timestamp": 303882.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "path": [8, 17, 3, 9], - "timestamp": 303885.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "format", - "type": "promptTemplate", - "configuration": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n" - }, - "metadata": { - "title": "Reply Structure Formatter", - "description": "Formatting the reply structure for the agent." - } - }, - "inputs": { - "template": "Reply as valid JSON of the following format:\n\n```json\n{{schemish}}\n```\n", - "schemish": { - "adCampaign": { - "headlines": [ - "string, an ad headline (30 character limit, up to 15 headlines)" - ], - "descriptions": [ - "string, the description (90 character limit, up to 4 descriptions)" - ] - } - } - }, - "outputs": { - "prompt": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n", - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [8, 17, 3, 9], - "timestamp": 303886.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [8, 17, 3, 10], - "timestamp": 303886.6999999881 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#buildContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "buildContext-input", - "to": "buildContext-run", - "out": "*" - }, - { - "from": "buildContext-run", - "to": "buildContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - { - "id": "buildContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 17, 3, 10], - "timestamp": 303887.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 17, 3, 10, 1], - "timestamp": 303887.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "validatorMetadata": [], - "path": [8, 17, 3, 10, 1], - "timestamp": 303888.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "path": [8, 17, 3, 10, 2], - "timestamp": 303889.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-run", - "type": "runJavascript", - "configuration": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true - } - }, - "inputs": { - "code": "function buildContext({context,format,instruction}) {if(!Array.isArray(context)){const text=typeof context===\"string\"?context:JSON.stringify(context);context=[{role:\"user\",parts:[{text}]}]}const list=context||[];if(list.length>0){const last=list[list.length-1];if(last.role===\"user\"){last.parts.unshift({text:instruction},{text:format});return{context:list}}}return{context:[...list,{role:\"user\",parts:[{text:instruction},{text:format}]}]}}", - "name": "buildContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [8, 17, 3, 10, 2], - "timestamp": 303893 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 17, 3, 10, 3], - "timestamp": 303893.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 17, 3, 10, 3], - "timestamp": 303894.5 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 17, 3, 10], - "timestamp": 303895 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "buildContext", - "type": "invoke", - "configuration": { - "$board": "#buildContext" - }, - "metadata": { - "title": "Build Context", - "description": "Building the context for the agent" - } - }, - "inputs": { - "$board": "#buildContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.", - "format": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "validatorMetadata": [], - "path": [8, 17, 3, 10], - "timestamp": 303895.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [8, 17, 3, 11], - "timestamp": 303896 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#count", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "count-input", - "to": "count-run", - "out": "*" - }, - { - "from": "count-run", - "to": "count-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "count-input", - "type": "input", - "configuration": {} - }, - { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - { - "id": "count-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 17, 3, 11], - "timestamp": 303896.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 17, 3, 11, 1], - "timestamp": 303897.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "validatorMetadata": [], - "path": [8, 17, 3, 11, 1], - "timestamp": 303897.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "path": [8, 17, 3, 11, 2], - "timestamp": 303898.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-run", - "type": "runJavascript", - "configuration": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true - } - }, - "inputs": { - "code": "function count({context,error,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:error}}", - "name": "count", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [8, 17, 3, 11, 2], - "timestamp": 303901.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [8, 17, 3, 11, 3], - "timestamp": 303901.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "path": [8, 17, 3, 11, 3], - "timestamp": 303902.5 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 17, 3, 11], - "timestamp": 303903.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "count", - "type": "invoke", - "configuration": { - "$board": "#count" - }, - "metadata": { - "title": "Counter", - "description": "Counting the JSON healing iteration" - } - }, - "inputs": { - "$board": "#count", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 5, - "error": "stub" - }, - "outputs": { - "continue": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "count": 4 - }, - "validatorMetadata": [], - "path": [8, 17, 3, 11], - "timestamp": 303903.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "path": [8, 17, 3, 14], - "timestamp": 303905.59999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/gemini-kit/graphs/kit.json#text", - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "version": "0.0.2", - "edges": [ - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - }, - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeURL", - "out": "model", - "in": "model" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - } - ], - "nodes": [ - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "format": "stream", - "description": "The generated text" - } - } - } - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "result", - "description": "The result of the Jsonata expression", - "type": "string" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "title": "json", - "description": "The JSON object to evaluate", - "type": ["object", "string"] - } - }, - "required": ["chunk"] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "toolCalls": { - "type": "array", - "items": { - "type": "object" - }, - "title": "Tool Calls", - "description": "The generated tool calls" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - } - ], - "kits": [], - "graphs": {} - }, - "path": [8, 17, 3, 14], - "timestamp": 303906.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "path": [8, 17, 3, 14, 1], - "timestamp": 303907.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": ["What is the square root of pi?"] - }, - "model": { - "type": "string", - "title": "Model", - "description": "The model to use for generation", - "enum": ["gemini-pro", "gemini-ultra"], - "examples": ["gemini-pro"] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "items": { - "type": "object", - "behavior": ["board"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ] - }, - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ] - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "items": { - "type": "string" - }, - "default": "[]" - } - }, - "required": ["text"] - } - }, - "outputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "validatorMetadata": [], - "path": [8, 17, 3, 14, 1], - "timestamp": 303907.7999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "path": [8, 17, 3, 14, 2], - "timestamp": 303908.2999999821 - } - }, - { - "type": "secret", - "data": { - "keys": ["GEMINI_KEY"], - "timestamp": 303909 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": ["GEMINI_KEY"] - } - }, - "inputs": { - "keys": ["GEMINI_KEY"] - }, - "outputs": { - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [8, 17, 3, 14, 2], - "timestamp": 303910 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "path": [8, 17, 3, 14, 3], - "timestamp": 303912.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true - } - }, - "inputs": { - "name": "chooseMethodFunction", - "code": "function chooseMethodFunction({ useStreaming }) {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n }", - "raw": true, - "useStreaming": false - }, - "outputs": { - "method": "generateContent", - "sseOption": "" - }, - "validatorMetadata": [], - "path": [8, 17, 3, 14, 3], - "timestamp": 303915.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "path": [8, 17, 3, 14, 4], - "timestamp": 303916.1999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - "inputs": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - "model": "gemini-pro", - "GEMINI_KEY": "b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "method": "generateContent", - "sseOption": "" - }, - "outputs": { - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7" - }, - "validatorMetadata": [], - "path": [8, 17, 3, 14, 4], - "timestamp": 303917 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "path": [8, 17, 3, 14, 5], - "timestamp": 303917.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - "inputs": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or (context[-1].role!=\"user\" and context[-1].role!=\"function\") ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )", - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "model": "gemini-pro", - "tools": [], - "useStreaming": false, - "stopSequences": [] - }, - "outputs": { - "result": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "validatorMetadata": [], - "path": [8, 17, 3, 14, 5], - "timestamp": 303918.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "path": [8, 17, 3, 14, 6], - "timestamp": 303918.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - "inputs": { - "method": "POST", - "stream": false, - "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=b576eea9-5ae6-4e9d-9958-e798ad8dbff7", - "body": { - "contents": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - } - }, - "outputs": { - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "validatorMetadata": [], - "path": [8, 17, 3, 14, 6], - "timestamp": 307663.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "path": [8, 17, 3, 14, 11], - "timestamp": 307676 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - "inputs": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true, - "response": { - "candidates": [ - { - "content": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "finishReason": "STOP", - "index": 0, - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - ], - "promptFeedback": { - "safetyRatings": [ - { - "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HATE_SPEECH", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_HARASSMENT", - "probability": "NEGLIGIBLE" - }, - { - "category": "HARM_CATEGORY_DANGEROUS_CONTENT", - "probability": "NEGLIGIBLE" - } - ] - } - } - }, - "outputs": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}", - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - } - }, - "validatorMetadata": [], - "path": [8, 17, 3, 14, 11], - "timestamp": 307678.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - }, - "path": [8, 17, 3, 14, 13], - "timestamp": 307680.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - }, - "path": [8, 17, 3, 14, 13], - "timestamp": 307681.7999999821 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 17, 3, 14], - "timestamp": 307682.89999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "generate", - "type": "text", - "configuration": { - "text": "unused" - }, - "metadata": { - "title": "Generate", - "logLevel": "info", - "description": "Generating an answer" - } - }, - "inputs": { - "text": "unused", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - }, - "context": { - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "title": "Context", - "description": "The conversation context" - } - } - }, - "context": { - "parts": [ - { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - ], - "role": "model" - }, - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - }, - "validatorMetadata": [], - "path": [8, 17, 3, 14], - "timestamp": 307684.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - }, - "path": [8, 17, 3, 16], - "timestamp": 307687.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "validate", - "type": "validateJson", - "configuration": {}, - "metadata": { - "title": "Validate JSON", - "logLevel": "info", - "description": "Checking my work" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "json": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "validatorMetadata": [], - "path": [8, 17, 3, 16], - "timestamp": 307696.5 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "path": [8, 17, 3, 19], - "timestamp": 307699.1999999881 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=structuredWorker#assembleContext", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "assembleContext-input", - "to": "assembleContext-run", - "out": "*" - }, - { - "from": "assembleContext-run", - "to": "assembleContext-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 17, 3, 19], - "timestamp": 307700.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 17, 3, 19, 1], - "timestamp": 307701.39999997616 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "validatorMetadata": [], - "path": [8, 17, 3, 19, 1], - "timestamp": 307702.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "path": [8, 17, 3, 19, 2], - "timestamp": 307703.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-run", - "type": "runJavascript", - "configuration": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true - } - }, - "inputs": { - "code": "function assembleContext({context,json:json2}) {if(!context)throw new Error(\"Context is required\");return{context:[...context,{role:\"model\",parts:{text:JSON.stringify(json2)}}]}}", - "name": "assembleContext", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 17, 3, 19, 2], - "timestamp": 307707.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 17, 3, 19, 3], - "timestamp": 307709 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 17, 3, 19, 3], - "timestamp": 307709.89999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 17, 3, 19], - "timestamp": 307710.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "assembleContext", - "type": "invoke", - "configuration": { - "$board": "#assembleContext" - }, - "metadata": { - "title": "Assemble Context", - "description": "Assembling the context for the agent" - } - }, - "inputs": { - "$board": "#assembleContext", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 17, 3, 19], - "timestamp": 307711.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 17, 3, 20], - "timestamp": 307712.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 17, 3, 20], - "timestamp": 307713 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 17, 3], - "timestamp": 307713.6999999881 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "instruction": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "title": "json", - "description": "The validated JSON.", - "type": "string" - } - } - }, - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 17, 3], - "timestamp": 307714.39999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 17, 6], - "timestamp": 307716.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 17, 6], - "timestamp": 307717.89999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 17], - "timestamp": 307718.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "invokeAgent", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke Worker", - "description": "Invoking the worker" - } - }, - "inputs": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 17], - "timestamp": 307719.1999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - "inputs": { - "$board": "#counter", - "count": 1, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 18], - "timestamp": 307719.89999997616 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "https://raw.githubusercontent.com/breadboard-ai/breadboard/main/packages/agent-kit/agent.kit.json?graph=repeater#counter", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "counter-input", - "to": "counter-run", - "out": "*" - }, - { - "from": "counter-run", - "to": "counter-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - { - "id": "counter-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [8, 18], - "timestamp": 307721.2999999821 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [8, 18, 1], - "timestamp": 307722 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "count": 1, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 18, 1], - "timestamp": 307722.89999997616 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - "inputs": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true, - "count": 1, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 18, 2], - "timestamp": 307723.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-run", - "type": "runJavascript", - "configuration": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true - } - }, - "inputs": { - "code": "function counter({context,count}) {const num=count-1;if(num!=0){return{continue:context,count:num}}return{stop:context}}", - "name": "counter", - "raw": true, - "count": 1, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "stop": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 18, 2], - "timestamp": 307727.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "counter-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "stop": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 18, 3], - "timestamp": 307728.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "stop": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 18, 3], - "timestamp": 307729.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [8, 18], - "timestamp": 307730.09999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "counter", - "type": "invoke", - "configuration": { - "$board": "#counter" - }, - "metadata": { - "title": "Counter", - "description": "Counting the number of repetitions" - } - }, - "inputs": { - "$board": "#counter", - "count": 1, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "stop": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8, 18], - "timestamp": 307730.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 19], - "timestamp": 307731.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [8, 19], - "timestamp": 307732.59999999404 - } - }, - { - "type": "graphend", - "data": { - "path": [8], - "timestamp": 307733.2999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "repeater-8", - "type": "repeater", - "configuration": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4 - }, - "metadata": { - "title": "Ad refinery", - "visual": { - "x": 1250, - "y": 71 - } - } - }, - "inputs": { - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "invoke", - "configuration": { - "$board": "#fn-3" - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "title": "Context", - "type": "array", - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[]", - "examples": ["the universe within us"] - } - }, - "required": ["context"] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": { - "fn-3": { - "edges": [ - { - "from": "fn-3-input", - "to": "fn-3-run", - "out": "*" - }, - { - "from": "fn-3-run", - "to": "fn-3-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-3-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-3-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_3({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}}", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-3-output", - "type": "output", - "configuration": {} - } - ] - } - } - } - }, - "max": 4, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - } - ] - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [8], - "timestamp": 307734.09999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-9", - "type": "invoke", - "configuration": { - "$board": "#fn-9" - }, - "metadata": { - "title": "JSON Extractor", - "visual": { - "x": 1443, - "y": 177 - } - } - }, - "inputs": { - "$board": "#fn-9", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [9], - "timestamp": 307737.09999999404 - } - }, - { - "type": "graphstart", - "data": { - "graph": { - "url": "http://localhost:5173/graphs/ad-writer-2.json#fn-9", - "$schema": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.4.0/packages/schema/breadboard.schema.json", - "edges": [ - { - "from": "fn-9-input", - "to": "fn-9-run", - "out": "*" - }, - { - "from": "fn-9-run", - "to": "fn-9-output", - "out": "*" - } - ], - "nodes": [ - { - "id": "fn-9-input", - "type": "input", - "configuration": {} - }, - { - "id": "fn-9-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true - } - }, - { - "id": "fn-9-output", - "type": "output", - "configuration": {} - } - ], - "kits": [] - }, - "path": [9], - "timestamp": 307738.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-9-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "path": [9, 1], - "timestamp": 307739.7999999821 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-9-input", - "type": "input", - "configuration": {} - }, - "inputs": {}, - "outputs": { - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "validatorMetadata": [], - "path": [9, 1], - "timestamp": 307741 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-9-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true - } - }, - "inputs": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "path": [9, 2], - "timestamp": 307741.59999999404 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-9-run", - "type": "runJavascript", - "configuration": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true - } - }, - "inputs": { - "code": "function fn_9({context}) {const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}}", - "name": "fn_9", - "raw": true, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "validatorMetadata": [], - "path": [9, 2], - "timestamp": 307745.59999999404 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "fn-9-output", - "type": "output", - "configuration": {} - }, - "inputs": { - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "path": [9, 3], - "timestamp": 307746.5 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-9-output", - "type": "output", - "configuration": {} - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "path": [9, 3], - "timestamp": 307747.5 - } - }, - { - "type": "graphend", - "data": { - "path": [9], - "timestamp": 307748 - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "fn-9", - "type": "invoke", - "configuration": { - "$board": "#fn-9" - }, - "metadata": { - "title": "JSON Extractor", - "visual": { - "x": 1443, - "y": 177 - } - } - }, - "inputs": { - "$board": "#fn-9", - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ] - }, - "outputs": { - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "validatorMetadata": [], - "path": [9], - "timestamp": 307748.6999999881 - } - }, - { - "type": "nodestart", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - } - }, - "metadata": { - "visual": { - "x": 1626, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "path": [10], - "timestamp": 307749.59999999404 - } - }, - { - "type": "output", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - } - }, - "metadata": { - "visual": { - "x": 1626, - "y": 71 - } - } - }, - "outputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "path": [10], - "timestamp": 307750.7999999821, - "bubbled": false - } - }, - { - "type": "nodeend", - "data": { - "node": { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - } - }, - "metadata": { - "visual": { - "x": 1626, - "y": 71 - } - } - }, - "inputs": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "json": { - "type": "string", - "title": "json" - } - } - }, - "context": [ - { - "role": "user", - "parts": [ - { - "text": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - }, - { - "text": "Write an ad for Breadboard. The ad must incorporate the following key messages: \n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs \n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a skeptical software developer. You are analytical, critical, and have a short attention span. You are always on the lookout for tools that will help you develop better software, but you are weary of ads and marketing hype. You are willing to provide constructive feedback to help improve the product.\n\nAs this persona, reply to an ad for Breadboard with the following key messages:\n- Breadboard for Developers\n- Play and experiment with AI Patterns\n- Prototype quickly\n- Use with Gemini APIs\n- Integrate AI Into Your Project\n- Create graphs with prompts\n- Accessible AI for Developers" - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"requirements\": [\n {\n \"requirement\": \"string, the requirement\",\n \"justification\": \"string, reasoning behind including this requirement\"\n }\n ]\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"requirements\":[{\"requirement\":\"Clear and concise documentation\",\"justification\":\"As a developer, I need well-documented APIs and tutorials to quickly understand how to use your product. This is especially important for a complex tool like Breadboard that integrates with other services.\"},{\"requirement\":\"Real-world examples and case studies\",\"justification\":\"I want to see how other developers have used Breadboard to solve real-world problems. This will help me understand the potential of the tool and how it can benefit my own projects.\"},{\"requirement\":\"A free trial or sandbox environment\",\"justification\":\"I'm not going to commit to a paid subscription without first trying out the product. A free trial or sandbox environment will allow me to experiment with Breadboard and see if it meets my needs.\"},{\"requirement\":\"Excellent customer support\",\"justification\":\"I need to know that I can get help if I run into any problems using Breadboard. Responsive and knowledgeable customer support is essential.\"}]}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\"." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Developers, Revolutionize AI with Breadboard!\",\"Unlock the Power of AI with Breadboard's Playground\",\"Prototype AI Solutions in a Flash with Breadboard\",\"Integrate AI Seamlessly with Breadboard and Gemini APIs\",\"Empower Your Projects with Breadboard's Accessible AI\",\"Visualize AI Insights with Breadboard's Graph Creation\",\"Breadboard: Where Developers and AI Unite\",\"Play, Experiment, and Innovate with Breadboard's AI Toolkit\",\"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\",\"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\",\"Developers, Supercharge Your Projects with Breadboard's AI Engine\",\"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\",\"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\",\"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\",\"Breadboard: Empowering Developers to Build the Future of AI\"],\"descriptions\":[\"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\",\"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\",\"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\",\"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Developers, Revolutionize AI with Breadboard!\" is 45 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock the Power of AI with Breadboard's Playground\" is 51 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype AI Solutions in a Flash with Breadboard\" is 49 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI Seamlessly with Breadboard and Gemini APIs\" is 55 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Your Projects with Breadboard's Accessible AI\" is 53 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Visualize AI Insights with Breadboard's Graph Creation\" is 54 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Where Developers and AI Unite\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play, Experiment, and Innovate with Breadboard's AI Toolkit\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Accelerate Your AI Journey with Breadboard's Developer-Friendly Platform\" is 72 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock Limitless AI Possibilities with Breadboard's Cutting-Edge Tools\" is 70 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Developers, Supercharge Your Projects with Breadboard's AI Engine\" is 65 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: The Ultimate Sandbox for AI Exploration and Experimentation\" is 71 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype and Iterate Rapidly with Breadboard's Agile AI Framework\" is 66 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI into Your Projects with Breadboard's Comprehensive APIs\" is 68 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering Developers to Build the Future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard empowers developers to play and experiment with AI patterns, prototype quickly, and integrate AI into their projects seamlessly. Unleash the power of Gemini APIs to enhance your AI capabilities.\" is 205 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard makes AI accessible for developers. With our user-friendly interface and developer-centric tools, you can create stunning graphs with simple prompts, bringing AI insights to life.\" is 190 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard's cutting-edge platform accelerates your AI journey. Prototype and iterate rapidly with our agile framework, and leverage our comprehensive APIs to integrate AI into your projects effortlessly.\" is 204 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Join the AI revolution with Breadboard. Our developer-friendly platform empowers you to build innovative AI solutions that transform industries and shape the future of technology.\" is 179 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Unlock AI's Power with Breadboard\",\"Prototype AI with Breadboard\",\"Integrate AI with Breadboard & Gemini\",\"Empower Projects with Breadboard AI\",\"Visualize AI with Breadboard\",\"Breadboard: Developers & AI\",\"Play & Innovate with Breadboard AI\",\"Accelerate AI with Breadboard\",\"Unlock AI with Breadboard\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: AI for Developers\"],\"descriptions\":[\"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\",\"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\",\"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\",\"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\"]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Unlock AI's Power with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard & Gemini\" is 37 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe description \"Breadboard: Play, prototype, and integrate AI with ease. Enhance your AI capabilities with Gemini APIs.\" is 103 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accessible AI for developers. Create graphs with prompts, bringing AI insights to life.\" is 99 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Accelerate your AI journey. Prototype rapidly, iterate effortlessly, and integrate AI seamlessly.\" is 109 characters long, but needs to be 90 characters. Shorten it.\n\nThe description \"Breadboard: Empowering developers to build the future of AI with our developer-friendly platform.\" is 97 characters long, but needs to be 90 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard!\",\"Unlock AI's Power!\",\"Integrate AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, and integrate AI with ease.\",\"Breadboard: Accessible AI for developers.\",\"Breadboard: Accelerate your AI journey.\",\"Breadboard: Empowering developers to build the future of AI.\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard!\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, and integrate AI with ease.\" is 56 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers.\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey.\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI.\" is 60 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - }, - { - "role": "user", - "parts": [ - { - "text": "You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:\n\nThe headline \"Revolutionize AI with Breadboard\" is 32 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Empower Projects with Breadboard AI\" is 35 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Play & Innovate with Breadboard AI\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Supercharge Projects with Breadboard AI\" is 39 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: AI Exploration Sandbox\" is 34 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Prototype Rapidly with Breadboard\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Integrate AI with Breadboard APIs\" is 33 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Play, prototype, integrate AI\" is 41 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accessible AI for developers\" is 40 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Accelerate your AI journey\" is 38 characters long, but needs to be 30 characters. Shorten it.\n\nThe headline \"Breadboard: Empowering developers to build the future of AI\" is 59 characters long, but needs to be 30 characters. Shorten it." - }, - { - "text": "Reply as valid JSON of the following format:\n\n```json\n{\n \"adCampaign\": {\n \"headlines\": [\n \"string, an ad headline (30 character limit, up to 15 headlines)\"\n ],\n \"descriptions\": [\n \"string, the description (90 character limit, up to 4 descriptions)\"\n ]\n }\n}\n```\n" - } - ] - }, - { - "role": "model", - "parts": { - "text": "{\"adCampaign\":{\"headlines\":[\"Revolutionize AI with Breadboard\",\"Empower Projects with Breadboard AI\",\"Play & Innovate with Breadboard AI\",\"Supercharge Projects with Breadboard AI\",\"Breadboard: AI Exploration Sandbox\",\"Prototype Rapidly with Breadboard\",\"Integrate AI with Breadboard APIs\",\"Breadboard: Play, prototype, integrate AI\",\"Breadboard: Accessible AI for developers\",\"Breadboard: Accelerate your AI journey\",\"Breadboard: Empowering developers to build the future of AI\"],\"descriptions\":[]}}" - } - } - ], - "json": { - "adCampaign": { - "headlines": [ - "Revolutionize AI with Breadboard", - "Empower Projects with Breadboard AI", - "Play & Innovate with Breadboard AI", - "Supercharge Projects with Breadboard AI", - "Breadboard: AI Exploration Sandbox", - "Prototype Rapidly with Breadboard", - "Integrate AI with Breadboard APIs", - "Breadboard: Play, prototype, integrate AI", - "Breadboard: Accessible AI for developers", - "Breadboard: Accelerate your AI journey", - "Breadboard: Empowering developers to build the future of AI" - ], - "descriptions": [] - } - } - }, - "validatorMetadata": [], - "path": [10], - "timestamp": 307751.39999997616 - } - }, - { - "type": "graphend", - "data": { - "path": [], - "timestamp": 307754.5 - } - } -] diff --git a/packages/breadboard/tests/inspector/data/simplest-no-schema-strict.json b/packages/breadboard/tests/inspector/data/simplest-no-schema-strict.json deleted file mode 100644 index 423fc72659a..00000000000 --- a/packages/breadboard/tests/inspector/data/simplest-no-schema-strict.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "title": "The simplest LLM-based board", - "description": "This board is as simple as it gets: takes text as input and invokes Gemini to generate a text response as output.", - "version": "0.0.3", - "edges": [ - { - "from": "gemini", - "to": "response", - "out": "text", - "in": "text" - }, - { - "from": "text", - "to": "gemini", - "out": "text", - "in": "text" - } - ], - "nodes": [ - { - "id": "response", - "type": "output" - }, - { - "id": "gemini", - "type": "invoke", - "configuration": { - "path": "gemini-generator-no-schema.json" - } - }, - { - "id": "text", - "type": "input" - } - ], - "graphs": {} -} diff --git a/packages/breadboard/tests/inspector/data/simplest-no-schema.json b/packages/breadboard/tests/inspector/data/simplest-no-schema.json deleted file mode 100644 index 11555b7573f..00000000000 --- a/packages/breadboard/tests/inspector/data/simplest-no-schema.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "title": "The simplest LLM-based board", - "description": "This board is as simple as it gets: takes text as input and invokes Gemini to generate a text response as output.", - "version": "0.0.3", - "edges": [ - { - "from": "gemini", - "to": "response", - "out": "*", - "in": "" - }, - { - "from": "text", - "to": "gemini", - "out": "*", - "in": "" - } - ], - "nodes": [ - { - "id": "response", - "type": "output" - }, - { - "id": "gemini", - "type": "invoke", - "configuration": { - "path": "gemini-generator-no-schema.json" - } - }, - { - "id": "text", - "type": "input" - } - ], - "graphs": {} -} diff --git a/packages/breadboard/tests/inspector/data/simplest.json b/packages/breadboard/tests/inspector/data/simplest.json deleted file mode 100644 index d6e31167136..00000000000 --- a/packages/breadboard/tests/inspector/data/simplest.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "title": "The simplest LLM-based board", - "description": "This board is as simple as it gets: takes text as input and invokes Gemini to generate a text response as output.", - "version": "0.0.3", - "edges": [ - { - "from": "gemini", - "to": "response", - "out": "*", - "in": "" - }, - { - "from": "text", - "to": "gemini", - "out": "*", - "in": "" - } - ], - "nodes": [ - { - "id": "response", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Response", - "description": "The completion generated by the LLM" - } - }, - "required": [ - "text" - ] - } - } - }, - { - "id": "gemini", - "type": "invoke", - "configuration": { - "path": "gemini-generator.json" - } - }, - { - "id": "text", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Prompt", - "description": "The prompt to generate a completion for", - "examples": [ - "Tell me a fun story about playing with breadboards" - ] - } - }, - "required": [ - "text" - ] - } - } - } - ], - "graphs": {} -} \ No newline at end of file diff --git a/packages/breadboard/tests/inspector/default-data-store.ts b/packages/breadboard/tests/inspector/default-data-store.ts deleted file mode 100644 index b8447c3cbc0..00000000000 --- a/packages/breadboard/tests/inspector/default-data-store.ts +++ /dev/null @@ -1,329 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { - createDefaultDataStore, - isInlineData, - isLLMContent, - isStoredData, - StoredDataCapabilityPart, -} from "../../src/index.js"; -import { HarnessRunResult } from "../../src/harness/types.js"; -import { isLLMContentArray } from "../../src/data/common.js"; - -const inputResult: HarnessRunResult = { - type: "nodeend", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - }, - inputs: {}, - path: [], - timestamp: 10, - outputs: { - content: { - role: "user", - parts: [ - { - inlineData: { - data: "aabbcc", - mimeType: "text/plain", - }, - }, - ], - }, - }, - }, - async reply() {}, -}; - -const inputResultArray: HarnessRunResult = { - type: "nodeend", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - }, - inputs: {}, - path: [], - timestamp: 10, - outputs: { - content: [ - { - role: "user", - parts: [ - { - inlineData: { - data: "aabbcc", - mimeType: "text/plain", - }, - }, - ], - }, - { - role: "user", - parts: [ - { - inlineData: { - data: "aabbcc", - mimeType: "text/plain", - }, - }, - ], - }, - ], - }, - }, - async reply() {}, -}; - -function copyResult(result: HarnessRunResult): HarnessRunResult { - // We can't use structuredClone because of the async function, so we fall back - // to using parse/stringify to make a copy. - return JSON.parse(JSON.stringify(result)); -} - -test("Default Data Store replaces inline data parts for LLM Content", async (t) => { - const store = createDefaultDataStore(); - const result = copyResult(inputResult); - - if (!(result.type === "nodeend")) { - t.fail("Result is not a nodeend"); - return; - } - - for (const property of Object.values(result.data.outputs)) { - if (!isLLMContent(property)) { - continue; - } - - for (const part of property.parts) { - t.truthy(isInlineData(part)); - } - } - - store.createGroup("store"); - await store.replaceDataParts("store", result); - - for (const property of Object.values(result.data.outputs)) { - if (!isLLMContent(property)) { - continue; - } - - for (const part of property.parts) { - t.truthy(isStoredData(part)); - } - } - - store.releaseAll(); -}); - -test("Default Data Store replaces inline data parts for LLM Content Arrays", async (t) => { - const store = createDefaultDataStore(); - const result = copyResult(inputResultArray); - - if (!(result.type === "nodeend")) { - t.fail("Result is not a nodeend"); - return; - } - - for (const property of Object.values(result.data.outputs)) { - if (!isLLMContentArray(property)) { - continue; - } - - for (const llmEntry of property) { - for (const part of llmEntry.parts) { - t.truthy(isInlineData(part)); - } - } - } - - store.createGroup("store"); - await store.replaceDataParts("store", result); - - for (const property of Object.values(result.data.outputs)) { - if (!isLLMContentArray(property)) { - continue; - } - - for (const llmEntry of property) { - for (const part of llmEntry.parts) { - t.truthy(isStoredData(part)); - } - } - } - - store.releaseAll(); -}); - -test("Default Data Store replaces stored data parts for LLM Content", async (t) => { - const store = createDefaultDataStore(); - const result = copyResult(inputResult); - - if (!(result.type === "nodeend")) { - t.fail("Result is not a nodeend"); - return; - } - - store.createGroup("store"); - await store.replaceDataParts("store", result); - - const handles: string[] = []; - for (const property of Object.values(result.data.outputs)) { - if (!isLLMContent(property)) { - continue; - } - - for (const part of property.parts) { - t.truthy(isStoredData(part)); - const storedPart = part as StoredDataCapabilityPart; - handles.push(storedPart.storedData.handle); - } - } - - // Replace again, and confirm we have different blob URLs. - await store.replaceDataParts("store", result); - for (const property of Object.values(result.data.outputs)) { - if (!isLLMContent(property)) { - continue; - } - - for (let i = 0; i < property.parts.length; i++) { - const part = property.parts[i]; - t.truthy(isStoredData(part)); - const storedPart = part as StoredDataCapabilityPart; - t.notDeepEqual(handles[i], storedPart.storedData.handle); - } - } - - store.releaseAll(); -}); - -test("Default Data Store replaces stored data parts for LLM Content Arrays", async (t) => { - const store = createDefaultDataStore(); - const result = copyResult(inputResultArray); - - if (!(result.type === "nodeend")) { - t.fail("Result is not a nodeend"); - return; - } - - store.createGroup("store"); - await store.replaceDataParts("store", result); - - const handles: string[] = []; - for (const property of Object.values(result.data.outputs)) { - if (!isLLMContentArray(property)) { - continue; - } - - for (const llmEntry of property) { - for (const part of llmEntry.parts) { - t.truthy(isStoredData(part)); - const storedPart = part as StoredDataCapabilityPart; - handles.push(storedPart.storedData.handle); - } - } - } - - // Replace again, and confirm we have different blob URLs. - await store.replaceDataParts("store", result); - for (const property of Object.values(result.data.outputs)) { - if (!isLLMContentArray(property)) { - continue; - } - - for (const llmEntry of property) { - for (let i = 0; i < llmEntry.parts.length; i++) { - const part = llmEntry.parts[i]; - t.truthy(isStoredData(part)); - const storedPart = part as StoredDataCapabilityPart; - t.notDeepEqual(handles[i], storedPart.storedData.handle); - } - } - } - - store.releaseAll(); -}); - -test("Default Data Store stores blobs against the existing group", async (t) => { - const store = createDefaultDataStore(); - const blob = new Blob(["Hello, world!"], { type: "text/plain" }); - - store.createGroup("store"); - const part = await store.store(blob); - const retrieved = await store.retrieveAsBlob(part); - - await t.deepEqual(blob, retrieved); - store.releaseAll(); -}); - -test("Default Data Store stores blobs against other groups", async (t) => { - const store = createDefaultDataStore(); - const blob = new Blob(["Hello, world!"], { type: "text/plain" }); - - store.createGroup("blobs"); - - // Creating this group sets the default group in the store, so the test only - // passes if the blob is found in the right store. - store.createGroup("store"); - const part = await store.store(blob, "blobs"); - store.releaseGroup("store"); - - const retrieved = await store.retrieveAsBlob(part); - - await t.deepEqual(blob, retrieved); - store.releaseAll(); -}); - -test("Default Data Store releases groups", async (t) => { - const store = createDefaultDataStore(); - const result = copyResult(inputResult); - - if (!(result.type === "nodeend")) { - t.fail("Result is not a nodeend"); - return; - } - - store.createGroup("store"); - await store.replaceDataParts("store", result); - - store.createGroup("store2"); - await store.replaceDataParts("store2", result); - - store.releaseGroup("store"); - t.falsy(store.has("store")); - - store.releaseAll(); - t.falsy(store.has("store2")); -}); - -test("Default Data Store serializes groups", async (t) => { - const store = createDefaultDataStore(); - const result = copyResult(inputResult); - - if (!(result.type === "nodeend")) { - t.fail("Result is not a nodeend"); - return; - } - - store.createGroup("store"); - await store.replaceDataParts("store", result); - - const serialized = await store.serializeGroup("store"); - t.deepEqual(serialized?.length, 1); - t.truthy(serialized![0].handle); - t.deepEqual(serialized![0].inlineData, { - data: "aabbcQ==", - mimeType: "text/plain", - }); - - store.releaseAll(); -}); diff --git a/packages/breadboard/tests/inspector/default-run-store.ts b/packages/breadboard/tests/inspector/default-run-store.ts deleted file mode 100644 index 80acdc51378..00000000000 --- a/packages/breadboard/tests/inspector/default-run-store.ts +++ /dev/null @@ -1,244 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { - createDefaultRunStore, - isInlineData, - isLLMContent, - isLLMContentArray, - toStoredDataPart, -} from "../../src/index.js"; -import { HarnessRunResult } from "../../src/harness/types.js"; -import { results as inlineDataRunResults } from "./inline-data-run.js"; -import { results as inlineDataArrayRunResults } from "./inline-data-run-array.js"; - -const url = "http://www.example.com"; - -const inputResult: HarnessRunResult = { - type: "nodeend", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - }, - inputs: {}, - path: [], - timestamp: 10, - outputs: { - content: { - role: "user", - parts: [ - { - inlineData: { - data: "aabbcc", - mimeType: "text/plain", - }, - }, - ], - }, - }, - }, - async reply() {}, -}; - -function copyResult(result: HarnessRunResult): HarnessRunResult { - // We can't use structuredClone because of the async function, so we fall back - // to using parse/stringify to make a copy. - return JSON.parse(JSON.stringify(result)); -} - -const delay = (ms: number) => new Promise((r) => setTimeout(r, ms)); - -test("Default Run Store creates multiple stores per URL", async (t) => { - const runStore = createDefaultRunStore(); - - const runTimestamp = await runStore.start(url); - await runStore.stop(url, runTimestamp); - - // Wait 10ms so that the timestamps of the two runs don't clash. - await delay(10); - - const runTimestamp2 = await runStore.start(url); - await runStore.stop(url, runTimestamp2); - - const runs = await runStore.getStoredRuns(url); - t.is(runs.size, 2); - - await runStore.drop(); -}); - -test("Default Run Store writes data", async (t) => { - const runStore = createDefaultRunStore(); - const result = copyResult(inputResult); - const runTimestamp = await runStore.start(url); - await runStore.write(url, runTimestamp, result); - await runStore.stop(url, runTimestamp); - const runs = await runStore.getStoredRuns(url); - - t.is(runs.size, 1); - t.deepEqual(runs.get(runTimestamp)![0], result); - await runStore.drop(); -}); - -test("Default Run Store drops data", async (t) => { - const runStore = createDefaultRunStore(); - const result = copyResult(inputResult); - const runTimestamp = await runStore.start(url); - await runStore.write(url, runTimestamp, result); - await runStore.stop(url, runTimestamp); - await runStore.drop(); - const runs = await runStore.getStoredRuns(url); - t.is(runs.size, 0); -}); - -test("Default Run Store truncates data", async (t) => { - const runStore = createDefaultRunStore(); - const result = copyResult(inputResult); - - const runTimestamp = await runStore.start(url); - await runStore.write(url, runTimestamp, result); - await runStore.stop(url, runTimestamp); - - // Wait 10ms so that the timestamps of the two runs don't clash. - await delay(10); - - const runTimestamp2 = await runStore.start(url); - await runStore.write(url, runTimestamp2, result); - await runStore.stop(url, runTimestamp2); - - await runStore.truncate(url, 1); - const runs = await runStore.getStoredRuns(url); - t.is(runs.size, 1); - t.truthy(runs.get(runTimestamp2)); -}); - -test("IDBRunStore replaces storedData with inlineData when writing (LLM Content)", async (t) => { - // Step 1. Write the data in, converting inlineData parts to storedDataParts - // before they get written in. - const runStore = createDefaultRunStore(); - const timestamp = await runStore.start(url); - - for (const result of inlineDataRunResults) { - if (result.type === "nodeend" && result.data.node.type === "input") { - for (const output of Object.values(result.data.outputs)) { - if (!isLLMContent(output)) { - continue; - } - - for (let i = 0; i < output.parts.length; i++) { - const part = output.parts[i]; - if (!isInlineData(part)) { - continue; - } - - output.parts[i] = await toStoredDataPart(part); - } - } - } - - await runStore.write(url, timestamp, result); - } - - await runStore.stop(url, timestamp); - - // Step 2. Get the run. - const run = await runStore.getStoredRuns(url); - const runValues = [...run.values()]; - - t.is(run.size, 1); - t.is(runValues[0].length, 8); - t.is(runValues[0][3].type, "nodeend"); - - // Step 3. Assert we have an inlineData object. - const nodeToInspect = runValues[0][3]; - if ( - nodeToInspect.type === "nodeend" && - nodeToInspect.data.node.type === "input" - ) { - const outputs = Object.values(nodeToInspect.data.outputs); - t.is(outputs.length, 1); - for (const output of outputs) { - t.truthy(isLLMContent(output), "Output is not LLM Content"); - - if (isLLMContent(output)) { - for (const part of output.parts) { - t.truthy(isInlineData(part), "Part is not inlineData"); - } - } - } - } else { - t.fail("Unexpected node type"); - } - - await runStore.drop(); -}); - -test("IDBRunStore replaces storedData with inlineData when writing (LLM Content Array)", async (t) => { - // Step 1. Write the data in, converting inlineData parts to storedDataParts - // before they get written in. - const runStore = createDefaultRunStore(); - const timestamp = await runStore.start(url); - - for (const result of inlineDataArrayRunResults) { - if (result.type === "nodeend" && result.data.node.type === "input") { - for (const output of Object.values(result.data.outputs)) { - if (!isLLMContentArray(output)) { - continue; - } - - for (const entry of output) { - for (let i = 0; i < entry.parts.length; i++) { - const part = entry.parts[i]; - if (!isInlineData(part)) { - continue; - } - - entry.parts[i] = await toStoredDataPart(part); - } - } - } - } - - await runStore.write(url, timestamp, result); - } - - await runStore.stop(url, timestamp); - - // Step 2. Get the run. - const run = await runStore.getStoredRuns(url); - const runValues = [...run.values()]; - - t.is(run.size, 1); - t.is(runValues[0].length, 9); - t.is(runValues[0][3].type, "nodeend"); - - // Step 3. Assert we have an inlineData object. - const nodeToInspect = runValues[0][3]; - if ( - nodeToInspect.type === "nodeend" && - nodeToInspect.data.node.type === "input" - ) { - const outputs = Object.values(nodeToInspect.data.outputs); - t.is(outputs.length, 1); - for (const output of outputs) { - t.truthy(isLLMContentArray(output), "Output is not LLM Content Array"); - - if (isLLMContentArray(output)) { - for (const entry of output) { - for (const part of entry.parts) { - t.truthy(isInlineData(part), "Part is not inlineData"); - } - } - } - } - } else { - t.fail("Unexpected node type"); - } - - await runStore.drop(); -}); diff --git a/packages/breadboard/tests/inspector/describe.ts b/packages/breadboard/tests/inspector/describe.ts deleted file mode 100644 index 745db0ba97c..00000000000 --- a/packages/breadboard/tests/inspector/describe.ts +++ /dev/null @@ -1,240 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { inspectableGraph } from "../../src/inspector/graph.js"; -import { GraphDescriptor, Schema } from "../../src/types.js"; -import { createLoader } from "../../src/loader/index.js"; - -const BASE_URL = new URL("../../../tests/inspector/data/", import.meta.url); - -const load = async (url: string) => { - const base = BASE_URL; - const loader = createLoader(); - const result = await loader.load(url, { base }); - if (!result) return undefined; - return inspectableGraph(result); -}; - -test("simple graph description works as expected", async (t) => { - const graph = { - nodes: [ - { id: "a", type: "input" }, - { id: "b", type: "bar" }, - { id: "c", type: "output" }, - ], - edges: [ - { from: "a", to: "b", in: "foo", out: "text" }, - { from: "b", to: "c", in: "text", out: "bar" }, - ], - } satisfies GraphDescriptor; - const inspectable = inspectableGraph(graph); - const api = await inspectable.describe(); - t.deepEqual(api, { - inputSchema: { - additionalProperties: false, - type: "object", - properties: { - text: { type: "string" }, - }, - }, - outputSchema: { - additionalProperties: false, - type: "object", - properties: { - text: { type: "string" }, - }, - }, - }); -}); - -test("inspector API can describe the input in simplest.json", async (t) => { - const simplest = await load("simplest.json"); - if (!simplest) { - return t.fail("Graph is undefined"); - } - const input = simplest.nodesByType("input")[0]; - - const api = await input.describe(); - - t.deepEqual(api, { - inputSchema: { - type: "object", - additionalProperties: false, - properties: { - schema: { - type: "object", - title: "Schema", - behavior: ["json-schema", "ports-spec", "config"], - }, - }, - } satisfies Schema, - outputSchema: { - type: "object", - properties: { - text: { - description: "The prompt to generate a completion for", - examples: ["Tell me a fun story about playing with breadboards"], - title: "Prompt", - type: "string", - }, - }, - required: ["text"], - } satisfies Schema, - }); -}); - -test("inspector API can describe the input in simplest-no-schema.json", async (t) => { - const simplest = await load("simplest-no-schema.json"); - if (!simplest) { - return t.fail("Graph is undefined"); - } - const input = simplest.nodesByType("input")[0]; - - const api = await input.describe(); - - t.deepEqual(api, { - inputSchema: { - type: "object", - additionalProperties: false, - properties: { - schema: { - type: "object", - title: "Schema", - behavior: ["json-schema", "ports-spec", "config"], - }, - }, - } satisfies Schema, - outputSchema: { - type: "object", - properties: {}, - } satisfies Schema, - }); -}); - -test("inspector API can describe the input in simplest-no-schema-strict.json", async (t) => { - const simplest = await load("simplest-no-schema-strict.json"); - if (!simplest) { - return t.fail("Graph is undefined"); - } - const input = simplest.nodesByType("input")[0]; - - const api = await input.describe(); - - t.deepEqual(api, { - inputSchema: { - additionalProperties: false, - type: "object", - properties: { - schema: { - type: "object", - title: "Schema", - behavior: ["json-schema", "ports-spec", "config"], - }, - }, - } satisfies Schema, - outputSchema: { - type: "object", - properties: { - text: { type: "string" }, - }, - }, - }); -}); - -test("inspector API can describe the output in simplest.json", async (t) => { - const simplest = await load("simplest.json"); - if (!simplest) { - return t.fail("Graph is undefined"); - } - const output = simplest.nodesByType("output")[0]; - - const api = await output.describe(); - - t.deepEqual(api, { - inputSchema: { - type: "object", - properties: { - "*": { type: "string" }, - schema: { - type: "object", - title: "Schema", - behavior: ["json-schema", "ports-spec", "config"], - }, - text: { - type: "string", - title: "Response", - description: "The completion generated by the LLM", - }, - }, - required: ["text"], - } satisfies Schema, - outputSchema: { - additionalProperties: false, - type: "object", - properties: {}, - } satisfies Schema, - }); -}); - -test("inspector API can describe the output in simplest-no-schema.json", async (t) => { - const simplest = await load("simplest-no-schema.json"); - if (!simplest) { - return t.fail("Graph is undefined"); - } - const output = simplest.nodesByType("output")[0]; - - const api = await output.describe(); - - t.deepEqual(api, { - inputSchema: { - type: "object", - properties: { - schema: { - type: "object", - title: "Schema", - behavior: ["json-schema", "ports-spec", "config"], - }, - "*": { type: "string" }, - }, - } satisfies Schema, - outputSchema: { - additionalProperties: false, - type: "object", - properties: {}, - } satisfies Schema, - }); -}); - -test("inspector API can describe the output in simplest-no-schema-strict.json", async (t) => { - const simplest = await load("simplest-no-schema-strict.json"); - if (!simplest) { - return t.fail("Graph is undefined"); - } - const output = simplest.nodesByType("output")[0]; - - const api = await output.describe(); - - t.deepEqual(api, { - inputSchema: { - type: "object", - properties: { - schema: { - type: "object", - title: "Schema", - behavior: ["json-schema", "ports-spec", "config"], - }, - text: { type: "string" }, - }, - } satisfies Schema, - outputSchema: { - additionalProperties: false, - type: "object", - properties: {}, - } satisfies Schema, - }); -}); diff --git a/packages/breadboard/tests/inspector/edge.ts b/packages/breadboard/tests/inspector/edge.ts deleted file mode 100644 index 358efbf561b..00000000000 --- a/packages/breadboard/tests/inspector/edge.ts +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { inspectableGraph } from "../../src/inspector/graph.js"; - -test("InspectableEdge instances are stable for read-only graph", (t) => { - const graph = inspectableGraph({ - nodes: [ - { - id: "node0", - type: "foo", - }, - { - id: "node2", - type: "bar", - }, - ], - edges: [{ from: "node0", out: "out", to: "node2", in: "in" }], - }); - t.true(graph.hasEdge({ from: "node0", out: "out", to: "node2", in: "in" })); - t.assert(graph.edges()[0] === graph.edges()[0]); - - const edgeInstance1 = graph.edges()[0]; - - const node0 = graph.nodeById("node0"); - const edgeInstance2 = node0?.outgoing()[0]; - - const node2 = graph.nodeById("node2"); - const edgeInstance3 = node2?.incoming()[0]; - - t.assert(edgeInstance1 === edgeInstance2); - t.assert(edgeInstance2 === edgeInstance3); -}); - -test("InspectableEdge correctly reports the type of an edge", (t) => { - const graph = inspectableGraph({ - nodes: [ - { - id: "node0", - type: "foo", - }, - { - id: "node2", - type: "bar", - }, - ], - edges: [ - { from: "node0", out: "out", to: "node2", in: "in" }, - { from: "node0", out: "out", to: "node2", in: "in", constant: true }, - { from: "node2", out: "", to: "node0", in: "in", constant: true }, - { from: "node2", out: "*", to: "node0", in: "in", constant: true }, - ], - }); - const edges = graph.edges(); - t.assert(edges[0].type === "ordinary"); - t.assert(edges[1].type === "constant"); - t.assert(edges[2].type === "control"); - t.assert(edges[3].type === "star"); -}); diff --git a/packages/breadboard/tests/inspector/graph.ts b/packages/breadboard/tests/inspector/graph.ts deleted file mode 100644 index a8cc43402aa..00000000000 --- a/packages/breadboard/tests/inspector/graph.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { inspectableGraph } from "../../src/inspector/graph.js"; -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; - -test("inspectableGraph correctly reacts to edits", (t) => { - const graph: GraphDescriptor = { - nodes: [{ id: "a", type: "foo" }], - edges: [], - }; - const inspectable = inspectableGraph(graph); - t.deepEqual( - inspectable.nodes().map((n) => n.descriptor.id), - ["a"] - ); - const editReceiver = inspectable; - const edge = { from: "a", to: "b", out: "text", in: "text" }; - editReceiver.nodeStore.add({ id: "b", type: "bar" }); - editReceiver.edgeStore.add(edge); - graph.nodes.push({ id: "b", type: "bar" }); - graph.edges.push(edge); - - t.deepEqual( - inspectable.nodes().map((n) => n.descriptor.id), - ["a", "b"] - ); - t.is(inspectable.nodesByType("bar")?.[0], inspectable.nodeById("b")!); - t.true(inspectable.hasEdge(edge)); - t.is(inspectable.incomingForNode("b")?.[0].from, inspectable.nodeById("a")!); - - editReceiver.nodeStore.remove("b"); - editReceiver.edgeStore.remove(edge); - graph.nodes = graph.nodes.filter((n) => n.id !== "b"); - graph.edges = graph.edges.filter((e) => e !== edge); - - t.deepEqual( - inspectable.nodes().map((n) => n.descriptor.id), - ["a"] - ); - t.false(inspectable.hasEdge(edge)); -}); diff --git a/packages/breadboard/tests/inspector/index.ts b/packages/breadboard/tests/inspector/index.ts deleted file mode 100644 index 44f5a6cf877..00000000000 --- a/packages/breadboard/tests/inspector/index.ts +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { inspectableGraph } from "../../src/inspector/graph.js"; - -test("inspectableGraph nodes, nodeById, and nodesByType work as expected", (t) => { - const graph = { - nodes: [ - { id: "a", type: "foo" }, - { id: "b", type: "bar" }, - { id: "c", type: "foo" }, - ], - edges: [], - }; - const inspectable = inspectableGraph(graph); - t.deepEqual( - inspectable.nodes().map((n) => n.descriptor.id), - ["a", "b", "c"] - ); - t.deepEqual(inspectable.nodeById("a")?.descriptor.type, "foo"); - t.deepEqual(inspectable.nodeById("b")?.descriptor.type, "bar"); - t.deepEqual(inspectable.nodeById("c")?.descriptor.type, "foo"); - - t.deepEqual( - inspectable.nodesByType("foo").map((n) => n.descriptor.id), - ["a", "c"] - ); -}); - -test("inspectableGraph incomingForNode and outgoingForNode work as expected", (t) => { - const graph = { - nodes: [ - { id: "a", type: "foo" }, - { id: "b", type: "bar" }, - { id: "c", type: "foo" }, - ], - edges: [ - { from: "a", to: "b" }, - { from: "b", to: "c" }, - ], - }; - const inspectable = inspectableGraph(graph); - t.deepEqual( - inspectable.incomingForNode("b").map((e) => e.from.descriptor.id), - ["a"] - ); - t.deepEqual( - inspectable.outgoingForNode("b").map((e) => e.to.descriptor.id), - ["c"] - ); - const b = inspectable.nodeById("b"); - t.deepEqual( - b?.incoming().map((e) => e.from.descriptor.id), - ["a"] - ); - t.deepEqual( - b?.outgoing().map((e) => e.to.descriptor.id), - ["c"] - ); - t.deepEqual(inspectable.nodeById("a")?.isEntry(), true); - t.deepEqual(inspectable.nodeById("c")?.isExit(), true); - t.deepEqual(b?.isEntry(), false); - t.deepEqual(b?.isExit(), false); -}); - -test("Graph correctly returns entry nodes for a graph", (t) => { - const graph = { - nodes: [ - { id: "a", type: "foo" }, - { id: "b", type: "bar" }, - { id: "c", type: "foo" }, - ], - edges: [ - { from: "a", to: "b" }, - { from: "b", to: "c" }, - ], - }; - const inspectable = inspectableGraph(graph); - t.deepEqual( - inspectable.entries().map((n) => n.descriptor.id), - ["a"] - ); -}); diff --git a/packages/breadboard/tests/inspector/inline-data-run-array.ts b/packages/breadboard/tests/inspector/inline-data-run-array.ts deleted file mode 100644 index bc471c73ef7..00000000000 --- a/packages/breadboard/tests/inspector/inline-data-run-array.ts +++ /dev/null @@ -1,514 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "@google-labs/breadboard/harness"; - -export const results: HarnessRunResult[] = [ - { - type: "graphstart", - data: { - graph: { - title: "Blank board", - description: - "A blank board. Use it as a starting point for your creations.", - version: "0.0.1", - nodes: [ - { - type: "input", - id: "input", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 0, - y: 0, - collapsed: true, - }, - }, - }, - { - type: "output", - id: "output", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 173, - y: 0, - collapsed: true, - }, - }, - }, - ], - edges: [ - { - from: "input", - out: "context", - to: "output", - in: "context", - }, - ], - url: "idb://default/blank-board.bgl.json", - }, - path: [], - timestamp: 68300.29999999702, - }, - async reply() {}, - }, - { - type: "nodestart", - data: { - node: { - type: "input", - id: "input", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 0, - y: 0, - collapsed: true, - }, - }, - }, - inputs: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - path: [1], - timestamp: 68356.60000000149, - }, - async reply() {}, - }, - { - type: "input", - data: { - node: { - type: "input", - id: "input", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 0, - y: 0, - collapsed: true, - }, - }, - }, - inputArguments: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - path: [1], - bubbled: false, - timestamp: 68364.20000000298, - }, - async reply() {}, - }, - { - type: "nodeend", - data: { - node: { - type: "input", - id: "input", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 0, - y: 0, - collapsed: true, - }, - }, - }, - inputs: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - outputs: { - context: [ - { - role: "user", - parts: [ - { - inlineData: { - mimeType: "image/png", - data: "iVBORw0KGgoAAAANSUhEUgAAAUAAAADwCAYAAABxLb1rAAAAAXNSR0IArs4c6QAAD+hJREFUeF7t3UuIHNXbB+AzcYxBIYhoUHChEEQQvIyJcZF4iUQFNwrGpWJcutGNiAq6ERQR40ZQCChiiOjCRYwXjKIJmqhJMOBSsxbBeIMRdJKP0x89/5rJJJnqfrumz5ynIWBM1VvnPO+Z31R3VXdPnDx58mTyIECAQIUCEwKwwq6bMgECPQEBaCEQIFCtgACstvUmToCAALQGCBCoVkAAVtt6EydAQABaAwQIVCsgAKttvYkTICAArQECBKoVEIDVtt7ECRAQgNYAAQLVCgjAaltv4gQICEBrgACBagUEYLWtN3ECBASgNUCAQLUCArDa1ps4AQIC0BogQKBaAQFYbetNnAABAWgNECBQrYAArLb1Jk6AgAC0BggQqFZAAFbbehMnQEAAWgMECFQrIACrbb2JEyAgAK0BAgSqFRCA1bbexAkQEIDWAAEC1QoIwGpbb+IECAhAa4AAgWoFBGC1rTdxAgQEoDVAgEC1AgKw2tabOAECAtAaIECgWgEBWG3rTZwAAQFoDRAgUK2AAKy29SZOgIAAtAYIEKhWQABW23oTJ0BAAFoDBAhUKyAAq229iRMgIACtAQIEqhUQgNW23sQJEBCA1gABAtUKCMBqW2/iBAgIQGuAAIFqBQRgta03cQIEBKA1QIBAtQICsNrWmzgBAgLQGiBAoFoBAVht602cAAEBaA0QIFCtgACstvUmToCAALQGCBCoVkAAVtt6EydAQABaAwQIVCsgAKttvYkTICAArQECBKoVEIDVtt7ECRAQgNYAAQLVCgjAaltv4gQICEBrgACBagUEYLWtN3ECBASgNUCAQLUCArDa1ps4AQICsMA1cOONN/ZGPTExMTv6kydPphMnTqQjR44UOCNDJrA0AgJwadwHPurU1FRasWLFgvvnEDx06NDAte1IoDYBAVhQx99+++20ffv2OWd+/eHn8Mt/Dh8+XNCMDJXA0goIwKX1b3X05tlfDrtHH300bdu2rVUNGxMg8D8BAVjIali3bt2ckXq6W0jjDHOsBQTgWLfnf4PLFz76Fz1y+H3xxRdp9erVSz76/llpHtPZHnmba6+9Nr355ptn29S/E+hEQAB2wjzcQeaH39VXX53eeeed4YoG7H3DDTekc845p3UlZ6+tyewwIgEBOCLYqLKbN29Of/zxx+zZX77VZVwudNx5553pt99+G3iq33///cD72pFAhIAAjFAcUY3bbrst/f3337PV85lTPvPLZ4Dj8sgBffz48TnDyU/Vm3/ybTv9+xT7G+a/X3/99WnHjh3jMhXjqFBAAI5x0+c/9d2yZUt64YUXxnjEZx5aPlvMc2i+lnnw4ME0OTlZ7JwMvGwBATjG/Vu/fn3vzCk/nn/++XTXXXeN8WgXN7Tnnnsu7d69e3bjyy+/PH3wwQeL29lWBIIFBGAwaGS5HBaffPJJL/jyfy+Xx6ZNm9L09PTsdLwWuFw6W948BGB5PSt+xPmiTn7tsP9U+OOPP04XX3xx8fMygfIEBGB5PVsWI37llVfSzp0705VXXpnyW/zOO++8ZTEvkyhLQACW1S+jJUAgUEAABmIqRYBAWQICsKx+GS0BAoECAjAQUykCBMoSEIBl9ctoCRAIFBCAgZhKESBQloAALKtfRkuAQKCAAAzEVIoAgbIEBGBZ/TJaAgQCBQRgIKZSBAiUJSAAy+qX0RIgECggAAMxlSJAoCwBAVhWv4yWAIFAAQEYiDkupZ544ol0xx13LIsPUB0XU+NYngICcJn1dcOGDWlmZqb3SdK33HJLyh875UGAwMICAnCZrYzm94jkqfm05WXWYNMJFRCAoZxLX6z/ReV5JPk7e/OXDnkQIOAMsIo10AzAlStXpq+//nok8163bl2v7saNG9P27dtHcgxFCYxawBngqIU7rt8MwFWrVqX9+/eHj2Dr1q3p2LFjvbr5tcZDhw6FH0NBAl0ICMAulDs8RvM1wAsuuCB9+eWX4UdvfmG7AAznVbBDAQHYIXYXh2oG4OrVq9Pnn38efth77rkn/fLLL84Aw2UV7FpAAHYtPuLj9V+by4dZs2ZN2rNnT/gRH3jggfTzzz8LwHBZBbsWEIBdi4/4eDfddFM6ceJE7yhXXHFFev/998OP+NBDD6Uff/xRAIbLKti1gADsWnzEx9u0aVOanp7uHSWH4WuvvRZ+xMcffzzt27dvtq57DcOJFexIQAB2BN3VYbZt25aOHj3aO9zTTz+d7rvvvvBDv/jii+m9997r1Z2cnEwHDhwIP4aCBLoQEIBdKHd4jJ9++im9/PLL6aKLLkrPPvtsOvfcc8OP/umnn6annnqqV/eSSy5JH330UfgxFCTQhYAA7EJ5mR3j33//Tffee2/6/fff02OPPZbyfYEeBEoUEIAlds2YCRAIERCAIYyKECBQooAALLFrxkyAQIiAAAxhVIQAgRIFBGDLruW3mnnzf0s0mxMYUwEB2KIx/ffZ+gCAFmg2JTDGAgKwRXOaHzSwY8eOdN1117XY26YECIybgABs0ZHmBw3kt5jlt5p5ECBQroAAbNG75hngVVddlXbu3Nlib5sSIDBuAgKwRUeaZ4Cvv/56yoHoQYBAuQICsEXvmmeAa9euTbt27Wqxt00JEBg3AQHYoiNdfNx8i+HYlACBIQUEYAvAZgD6yskWcDYlMKYCArBFY5oBODMzk44cOdJib5sSIDBuAgKwRUeaAZh380nILfCCNt27d2969dVX04MPPpjuv//+oKrK1CogAFt0vhmA3g3SAi5w0/6V+OyfP4g1f/GTB4FBBQRgC7n169f3vgg8PwRgC7jATZu3IrkXMxC20lICsEXjb7755vTff//N7rFq1aq0f//+FhVsOqzA/B54GWJY0br3F4At++9pcEuw4M0feeSR9MMPP8yehT/zzDMj+eKn4GErN6YCArBlY6amptKKFSt6e+Xv3z18+HDLCjYfVqD5Syj34ttvvx22pP0rFRCALRvvSnBLsBFs3vzyd6/FjgC4opICsGWz83uA33jjjTQxMTH7NMwHpLZEHHLz5uuAAnBIzMp3F4ADLABngQOgBe7ianwgZuWlBOAAC6D5A5h3dyVyAMQhdmneCuMMcAhIuyYBOMAiaP4A9ncXggNADriLK/EDwtntFAEBOOCi8DR4QLiA3eb/AvLLJwC10hICcMDGzz8L+fDDD9Oll146YDW7tREQgG20bHsmAQE44Po4duxY2rp165y9nYkMiNlyN68BtgSz+WkFBOAQi8MP4hB4Q+zKfQg8u84REIBDLIj5V4O9K2EIzEXu+vDDD6ejR4/O3oeZX3bYvXv3Ive2GYG5AgJwyBXhiuSQgC139/pfSzCbn1FAAA65QNwSMyRgi93nn3G7B7AFnk0XFBCAAQtj/llg/pAEH5cfADuvhFuP4k1rrygAA1bA3XffnX799dc57w/+5ptv0sqVKwOqK5EF5p9p+1Iq6yJCQABGKC7wA+rpWRBsSr0voO9/+ES/qluO4nxrriQAA7s//ywl/9B+9913gUeoq9RCwecXS11rYNSzFYCBwtPT02njxo1zzlbcGjMYsPAbzM1e7QQEYDuvs26dzwLzWYqnbGelWnCDJ598Mn322Wen/Jszv8E87XVmAQE4ghWyYcOG3pcnNT809fzzz0/79u0bwdGWT8mFbinKwZf/+OqB5dPncZqJABxRNxZ6Crdr1660du3aER2x3LK33357+vPPP085a84zuuaaa9Jbb71V7uSMfKwFBOAI2+Pq5ZlxFzrjy3vkM7782qkLSCNcnEr3BATgiBeCK8OnAje/1Ggh/jVr1qQ9e/aMuDPKExCAI18DL730Unr33XdPOU6N97HNfytbE6V/4ahGl5EvQgc4rYAzwA4Wx0IXRSYnJ9PBgwc7OPrSHmLLli3p+PHjZxyEK7xL26Oajy4AO+r+/Kd9+Yc+P5brV2qe7nagPrerux0tPIc5o4AA7HCBTE1N9V7cb4bAcgrB/uudC90HmefZ///5lqCvvvqqQ3mHIrCwgADseGUsdAGg5KeAmzdvTn/99VfKn4Az/+bvZtDnf/P6XseLzeHOKiAAz0oUv8FCt8c0z5DGOSjyWWwOs/yn/zT+TMG3nM5w41eCikstIACXqAPNIJk/hPlPIfMFkwMHDizJSPvj7B/8dGHXHFzJZ7RLguygSyYgAJeM/v8PfLqbgU83rNO9vhY5jUGOkfe58MIL0969eyOHohaBkQoIwJHyLr54fm1wZmamt8NizrIWXzl+y35AOtOLt1WxWwEB2K33oo+WXyfMV4zzxYWlDMXm2WD+78suu8y3sC26izYcdwEBOO4daozv1ltvTf/880/v4kM/GPvh2Pz7oFPqX9zoX9F1hjeopP1KERCApXTKOAkQCBcQgOGkChIgUIqAACylU8ZJgEC4gAAMJ1WQAIFSBARgKZ0yTgIEwgUEYDipggQIlCIgAEvplHESIBAuIADDSRUkQKAUAQFYSqeMkwCBcAEBGE6qIAECpQgIwFI6ZZwECIQLCMBwUgUJEChFQACW0injJEAgXEAAhpMqSIBAKQICsJROGScBAuECAjCcVEECBEoREICldMo4CRAIFxCA4aQKEiBQioAALKVTxkmAQLiAAAwnVZAAgVIEBGApnTJOAgTCBQRgOKmCBAiUIiAAS+mUcRIgEC4gAMNJFSRAoBQBAVhKp4yTAIFwAQEYTqogAQKlCAjAUjplnAQIhAsIwHBSBQkQKEVAAJbSKeMkQCBcQACGkypIgEApAgKwlE4ZJwEC4QICMJxUQQIEShEQgKV0yjgJEAgXEIDhpAoSIFCKgAAspVPGSYBAuIAADCdVkACBUgQEYCmdMk4CBMIFBGA4qYIECJQiIABL6ZRxEiAQLiAAw0kVJECgFAEBWEqnjJMAgXABARhOqiABAqUICMBSOmWcBAiECwjAcFIFCRAoRUAAltIp4yRAIFxAAIaTKkiAQCkCArCUThknAQLhAgIwnFRBAgRKERCApXTKOAkQCBcQgOGkChIgUIqAACylU8ZJgEC4gAAMJ1WQAIFSBARgKZ0yTgIEwgUEYDipggQIlCIgAEvplHESIBAuIADDSRUkQKAUAQFYSqeMkwCBcAEBGE6qIAECpQgIwFI6ZZwECIQLCMBwUgUJEChFQACW0injJEAgXEAAhpMqSIBAKQICsJROGScBAuECAjCcVEECBEoREICldMo4CRAIFxCA4aQKEiBQioAALKVTxkmAQLiAAAwnVZAAgVIEBGApnTJOAgTCBQRgOKmCBAiUIiAAS+mUcRIgEC4gAMNJFSRAoBQBAVhKp4yTAIFwAQEYTqogAQKlCAjAUjplnAQIhAsIwHBSBQkQKEVAAJbSKeMkQCBcQACGkypIgEApAgKwlE4ZJwEC4QICMJxUQQIEShEQgKV0yjgJEAgXEIDhpAoSIFCKwP8B5wTti5uv54YAAAAASUVORK5CYII=", - }, - }, - ], - }, - ], - }, - path: [1], - timestamp: 70183.20000000298, - }, - async reply() {}, - }, - { - type: "nodestart", - data: { - node: { - type: "output", - id: "output", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 173, - y: 0, - collapsed: true, - }, - }, - }, - inputs: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - context: [ - { - role: "user", - parts: [ - { - storedData: { - handle: - "blob:http://localhost:5173/f28de4b7-0ace-4d76-912e-70ee79048053", - mimeType: "image/png", - }, - }, - ], - }, - ], - }, - path: [2], - timestamp: 70193.29999999702, - }, - async reply() {}, - }, - { - type: "output", - data: { - node: { - type: "output", - id: "output", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 173, - y: 0, - collapsed: true, - }, - }, - }, - outputs: { - context: [ - { - role: "user", - parts: [ - { - storedData: { - handle: - "blob:http://localhost:5173/f28de4b7-0ace-4d76-912e-70ee79048053", - mimeType: "image/png", - }, - }, - ], - }, - ], - }, - path: [2], - timestamp: 70203.60000000149, - bubbled: false, - }, - async reply() {}, - }, - { - type: "nodeend", - data: { - node: { - type: "output", - id: "output", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 173, - y: 0, - collapsed: true, - }, - }, - }, - inputs: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - context: [ - { - role: "user", - parts: [ - { - storedData: { - handle: - "blob:http://localhost:5173/f28de4b7-0ace-4d76-912e-70ee79048053", - mimeType: "image/png", - }, - }, - ], - }, - ], - }, - outputs: {}, - path: [2], - timestamp: 70207.89999999851, - }, - async reply() {}, - }, - { - type: "graphend", - data: { - path: [], - timestamp: 70210.39999999851, - }, - async reply() {}, - }, - { - type: "end", - data: { - timestamp: 70213.20000000298, - last: { - node: { - type: "output", - id: "output", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 173, - y: 0, - collapsed: true, - }, - }, - }, - missing: [], - }, - }, - async reply() {}, - }, -]; diff --git a/packages/breadboard/tests/inspector/inline-data-run.ts b/packages/breadboard/tests/inspector/inline-data-run.ts deleted file mode 100644 index d1a47ab6979..00000000000 --- a/packages/breadboard/tests/inspector/inline-data-run.ts +++ /dev/null @@ -1,362 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "@google-labs/breadboard/harness"; - -export const results: HarnessRunResult[] = [ - { - type: "graphstart", - data: { - graph: { - url: "idb://default/blank-board.bgl.json", - title: "Blank board", - description: - "A blank board. Use it as a starting point for your creations.", - $schema: - "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.5.1/packages/schema/breadboard.schema.json", - version: "0.0.1", - edges: [ - { - from: "input-45dd0a3d", - to: "output-b8d7ce06", - out: "content", - in: "content", - }, - ], - nodes: [ - { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - ], - kits: [], - }, - path: [], - timestamp: 2156.099999964237, - }, - async reply() {}, - }, - { - type: "nodestart", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - path: [1], - timestamp: 2167.2999999523163, - }, - async reply() {}, - }, - { - type: "input", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputArguments: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - path: [1], - bubbled: false, - timestamp: 2172.899999976158, - }, - async reply() {}, - }, - { - type: "nodeend", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - outputs: { - content: { - role: "user", - parts: [ - { - inlineData: { - data: "iVBORw0KGgoAAAANSUhEUgAAAPQAAAC3CAYAAAAl43M8AAAAAXNSR0IArs4c6QAACb1JREFUeF7t3buO1EwTgOGGRURIcAEEcAecxSkjJOAQEBBwA0gQkAESISIn5wKAjBCEkBDitAtCIiQDcQmc2U+9+md/M8ww9tgu7/Y+lhBasLtcb9U77mnveDYtLy8vJxsCCBRBYBOhi6ijJBBYIUBojYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVMxpqezbty9t3rw5LS8vr+yS/379+vXKv9nKIkDoNVDP27dvpzt37qzKloV78+ZNJ2c2knnSYNu3b0+PHj3qJI5B1gYBQq+BOuzfvz9t2rTpjzPJUi8uLrY+u38J/fv377S0tNQ6hgHWDgFCD1yLAwcOTDyDLmTLMucXitGLxWjKXf25ixeNgREKXyFA6IHbYZrQXVyhx6/8CwsL6efPn3/MBvJ7aVs5BAg9cC0nTbfzKXVxhZ42djVlQg/cAB2HJ3THQJsON+0KvWvXrnTv3r2mw/2x//iUu/qfXcwAWp2cg3shQOhesNYf9PDhwyvT4NGWRct/ulqs2rt378rtqeqiWx7/x48f6d27d/VP1J7rggChBy7T58+f08mTJ1cXr379+tXZLauBUxN+AAKEHgC6kAj0RYDQfZE1LgIDECD0ANCFRKAvAoTui6xxERiAAKEHgC4kAn0RIHRfZI2LwAAECD0AdCER6IsAofsia1wEBiBA6AGgC4lAXwQI3RdZ4yIwAAFCDwBdSAT6IkDoGWTPnTuXPnz4sLJX/j3rt2/f9lUL4yLQmgChZyCsPsLHRw5b95sBeiZA6BmAqw8JIHTP3Wj41gQI7QrduomaDPDx48e0c+fOJofYtwEBQhO6Qbu02/XKlSvpyZMnaevWrenZs2ftBnP0RAKEbiB03tUzuOY3qfq4pevXr6fTp0/PP5gjCT1PD1gUm4fa5GOq6xH50Uv5CwZs3RJwhbYo1m1H/WO0qtC7d+9Od+/eDYu9UQIRmtBhvV6dcp85cyZdu3YtLPZGCUToGZW+ceNGevDgwepTMz3Ebz41Tp06lT59+rR6sLWI+TjOOorQswillNyLrgHJTKc9pA5GIHQNiONCnz9/PuVbMLb6BKrTbb+gU59b0z0JXZNYVeouvqamZthidqvyyw/9f/XqVTG5raVECF2zGuPfE3Xp0qV04cKFmkdv7N2OHDmy8k0do+3s2bPp6tWrGxtKT9kTuibY8a+UcZWuCS6ldPDgwZWv9xltFsTqs2u6J6EbEBu/Slvxrgdv/Av5CF2P2zx7EboBtZs3b6b79++vHmFxpx48C2L1OHWxF6EbUqz+KqgpZD14VaG9VanHbN69CD0HufGpd/661pcvX84x0sY4pMprx44d6eHDhxsj8QGyJPQc0MeFNvWeDtGC2BwN1uIQQs8Jb3yhxwLZZJAWxOZssDkPI/Sc4PJhpt6z4VkQm82oyz0I3YJmvje9sLDwxwi3bt1KJ06caDFqWYe6QsfWk9AteY83bB7Ofdb/Q3WFbtlgDQ8ndENgk3Yfv5Xl1sxkob3QddBsM4YgdEeMx99Pu1L/vcZA6I6a7R/DELojxk+fPk2XL19efRBCHnaj385yy6qj5mowDKEbwJq16/Pnz9PFixdJ/T9QFsRmdUz3/0/ojpnu2bMnbdmy5a9RN+J004JYx81VYzhC14DUdJc81cwLY/mD/KMtT7+/fv2a3r9/33S4dbf/0aNH07dv3/7IfyO+oA1ROEL3RH3SPeosdb56v3jxoqeoww977NixlReu6ouZJ5TE1YXQPbL+/v17ylerSduXL1+Ku1ofP3485bzGZyaLi4s9UjZ0lQChA/ph0i2t0RM8Smn2SR8r3eir/AGt9VcIQgdRP3To0Mr76vEtN33++OV6fmhefsHKW/XKnH/2vjmouSphCB3MPK/8ZonHm38kxHoTe9rso5SZR3B7tA5H6NYImw8wWjiadFUbyb4erm7jvzgyIrEezr151dbHEYQeuE6TrnD5lEbvsdfiqvgkkUt46zBwK3QSntCdYGw3yKT71tUR18pVO68D5Ac5jM8s8vnlP0tLS+1AOLo1AUK3RtjtANOmseNRou7tTptBVM/HFLvbHmgzGqHb0Ovx2Gkrx9NCVh9kP2nBrY9TdVuqD6rtxiR0O369Hz263TUSNkrWSYmNpv75HLZt25YeP37ce/4CNCNA6Ga8Bt+7zhS4r5PMC3T5E2W2tUuA0Gu3No3ObPTeuzr1bjTAlJ3z1dh75C5IxoxB6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQIHQIZkEQiCFA6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQ+A+sTBEnEQXhEgAAAABJRU5ErkJggg==", - mimeType: "image/png", - }, - }, - ], - }, - }, - validatorMetadata: [], - path: [1], - timestamp: 16784.899999976158, - }, - async reply() {}, - }, - { - type: "nodestart", - data: { - node: { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - content: { - role: "user", - parts: [ - { - inlineData: { - data: "iVBORw0KGgoAAAANSUhEUgAAAPQAAAC3CAYAAAAl43M8AAAAAXNSR0IArs4c6QAACb1JREFUeF7t3buO1EwTgOGGRURIcAEEcAecxSkjJOAQEBBwA0gQkAESISIn5wKAjBCEkBDitAtCIiQDcQmc2U+9+md/M8ww9tgu7/Y+lhBasLtcb9U77mnveDYtLy8vJxsCCBRBYBOhi6ijJBBYIUBojYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVMxpqezbty9t3rw5LS8vr+yS/379+vXKv9nKIkDoNVDP27dvpzt37qzKloV78+ZNJ2c2knnSYNu3b0+PHj3qJI5B1gYBQq+BOuzfvz9t2rTpjzPJUi8uLrY+u38J/fv377S0tNQ6hgHWDgFCD1yLAwcOTDyDLmTLMucXitGLxWjKXf25ixeNgREKXyFA6IHbYZrQXVyhx6/8CwsL6efPn3/MBvJ7aVs5BAg9cC0nTbfzKXVxhZ42djVlQg/cAB2HJ3THQJsON+0KvWvXrnTv3r2mw/2x//iUu/qfXcwAWp2cg3shQOhesNYf9PDhwyvT4NGWRct/ulqs2rt378rtqeqiWx7/x48f6d27d/VP1J7rggChBy7T58+f08mTJ1cXr379+tXZLauBUxN+AAKEHgC6kAj0RYDQfZE1LgIDECD0ANCFRKAvAoTui6xxERiAAKEHgC4kAn0RIHRfZI2LwAAECD0AdCER6IsAofsia1wEBiBA6AGgC4lAXwQI3RdZ4yIwAAFCDwBdSAT6IkDoGWTPnTuXPnz4sLJX/j3rt2/f9lUL4yLQmgChZyCsPsLHRw5b95sBeiZA6BmAqw8JIHTP3Wj41gQI7QrduomaDPDx48e0c+fOJofYtwEBQhO6Qbu02/XKlSvpyZMnaevWrenZs2ftBnP0RAKEbiB03tUzuOY3qfq4pevXr6fTp0/PP5gjCT1PD1gUm4fa5GOq6xH50Uv5CwZs3RJwhbYo1m1H/WO0qtC7d+9Od+/eDYu9UQIRmtBhvV6dcp85cyZdu3YtLPZGCUToGZW+ceNGevDgwepTMz3Ebz41Tp06lT59+rR6sLWI+TjOOorQswillNyLrgHJTKc9pA5GIHQNiONCnz9/PuVbMLb6BKrTbb+gU59b0z0JXZNYVeouvqamZthidqvyyw/9f/XqVTG5raVECF2zGuPfE3Xp0qV04cKFmkdv7N2OHDmy8k0do+3s2bPp6tWrGxtKT9kTuibY8a+UcZWuCS6ldPDgwZWv9xltFsTqs2u6J6EbEBu/Slvxrgdv/Av5CF2P2zx7EboBtZs3b6b79++vHmFxpx48C2L1OHWxF6EbUqz+KqgpZD14VaG9VanHbN69CD0HufGpd/661pcvX84x0sY4pMprx44d6eHDhxsj8QGyJPQc0MeFNvWeDtGC2BwN1uIQQs8Jb3yhxwLZZJAWxOZssDkPI/Sc4PJhpt6z4VkQm82oyz0I3YJmvje9sLDwxwi3bt1KJ06caDFqWYe6QsfWk9AteY83bB7Ofdb/Q3WFbtlgDQ8ndENgk3Yfv5Xl1sxkob3QddBsM4YgdEeMx99Pu1L/vcZA6I6a7R/DELojxk+fPk2XL19efRBCHnaj385yy6qj5mowDKEbwJq16/Pnz9PFixdJ/T9QFsRmdUz3/0/ojpnu2bMnbdmy5a9RN+J004JYx81VYzhC14DUdJc81cwLY/mD/KMtT7+/fv2a3r9/33S4dbf/0aNH07dv3/7IfyO+oA1ROEL3RH3SPeosdb56v3jxoqeoww977NixlReu6ouZJ5TE1YXQPbL+/v17ylerSduXL1+Ku1ofP3485bzGZyaLi4s9UjZ0lQChA/ph0i2t0RM8Smn2SR8r3eir/AGt9VcIQgdRP3To0Mr76vEtN33++OV6fmhefsHKW/XKnH/2vjmouSphCB3MPK/8ZonHm38kxHoTe9rso5SZR3B7tA5H6NYImw8wWjiadFUbyb4erm7jvzgyIrEezr151dbHEYQeuE6TrnD5lEbvsdfiqvgkkUt46zBwK3QSntCdYGw3yKT71tUR18pVO68D5Ac5jM8s8vnlP0tLS+1AOLo1AUK3RtjtANOmseNRou7tTptBVM/HFLvbHmgzGqHb0Ovx2Gkrx9NCVh9kP2nBrY9TdVuqD6rtxiR0O369Hz263TUSNkrWSYmNpv75HLZt25YeP37ce/4CNCNA6Ga8Bt+7zhS4r5PMC3T5E2W2tUuA0Gu3No3ObPTeuzr1bjTAlJ3z1dh75C5IxoxB6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQIHQIZkEQiCFA6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQ+A+sTBEnEQXhEgAAAABJRU5ErkJggg==", - mimeType: "image/png", - }, - }, - ], - }, - }, - path: [2], - timestamp: 16792.099999964237, - }, - async reply() {}, - }, - { - type: "output", - data: { - node: { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - outputs: { - content: { - role: "user", - parts: [ - { - inlineData: { - data: "iVBORw0KGgoAAAANSUhEUgAAAPQAAAC3CAYAAAAl43M8AAAAAXNSR0IArs4c6QAACb1JREFUeF7t3buO1EwTgOGGRURIcAEEcAecxSkjJOAQEBBwA0gQkAESISIn5wKAjBCEkBDitAtCIiQDcQmc2U+9+md/M8ww9tgu7/Y+lhBasLtcb9U77mnveDYtLy8vJxsCCBRBYBOhi6ijJBBYIUBojYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVMxpqezbty9t3rw5LS8vr+yS/379+vXKv9nKIkDoNVDP27dvpzt37qzKloV78+ZNJ2c2knnSYNu3b0+PHj3qJI5B1gYBQq+BOuzfvz9t2rTpjzPJUi8uLrY+u38J/fv377S0tNQ6hgHWDgFCD1yLAwcOTDyDLmTLMucXitGLxWjKXf25ixeNgREKXyFA6IHbYZrQXVyhx6/8CwsL6efPn3/MBvJ7aVs5BAg9cC0nTbfzKXVxhZ42djVlQg/cAB2HJ3THQJsON+0KvWvXrnTv3r2mw/2x//iUu/qfXcwAWp2cg3shQOhesNYf9PDhwyvT4NGWRct/ulqs2rt378rtqeqiWx7/x48f6d27d/VP1J7rggChBy7T58+f08mTJ1cXr379+tXZLauBUxN+AAKEHgC6kAj0RYDQfZE1LgIDECD0ANCFRKAvAoTui6xxERiAAKEHgC4kAn0RIHRfZI2LwAAECD0AdCER6IsAofsia1wEBiBA6AGgC4lAXwQI3RdZ4yIwAAFCDwBdSAT6IkDoGWTPnTuXPnz4sLJX/j3rt2/f9lUL4yLQmgChZyCsPsLHRw5b95sBeiZA6BmAqw8JIHTP3Wj41gQI7QrduomaDPDx48e0c+fOJofYtwEBQhO6Qbu02/XKlSvpyZMnaevWrenZs2ftBnP0RAKEbiB03tUzuOY3qfq4pevXr6fTp0/PP5gjCT1PD1gUm4fa5GOq6xH50Uv5CwZs3RJwhbYo1m1H/WO0qtC7d+9Od+/eDYu9UQIRmtBhvV6dcp85cyZdu3YtLPZGCUToGZW+ceNGevDgwepTMz3Ebz41Tp06lT59+rR6sLWI+TjOOorQswillNyLrgHJTKc9pA5GIHQNiONCnz9/PuVbMLb6BKrTbb+gU59b0z0JXZNYVeouvqamZthidqvyyw/9f/XqVTG5raVECF2zGuPfE3Xp0qV04cKFmkdv7N2OHDmy8k0do+3s2bPp6tWrGxtKT9kTuibY8a+UcZWuCS6ldPDgwZWv9xltFsTqs2u6J6EbEBu/Slvxrgdv/Av5CF2P2zx7EboBtZs3b6b79++vHmFxpx48C2L1OHWxF6EbUqz+KqgpZD14VaG9VanHbN69CD0HufGpd/661pcvX84x0sY4pMprx44d6eHDhxsj8QGyJPQc0MeFNvWeDtGC2BwN1uIQQs8Jb3yhxwLZZJAWxOZssDkPI/Sc4PJhpt6z4VkQm82oyz0I3YJmvje9sLDwxwi3bt1KJ06caDFqWYe6QsfWk9AteY83bB7Ofdb/Q3WFbtlgDQ8ndENgk3Yfv5Xl1sxkob3QddBsM4YgdEeMx99Pu1L/vcZA6I6a7R/DELojxk+fPk2XL19efRBCHnaj385yy6qj5mowDKEbwJq16/Pnz9PFixdJ/T9QFsRmdUz3/0/ojpnu2bMnbdmy5a9RN+J004JYx81VYzhC14DUdJc81cwLY/mD/KMtT7+/fv2a3r9/33S4dbf/0aNH07dv3/7IfyO+oA1ROEL3RH3SPeosdb56v3jxoqeoww977NixlReu6ouZJ5TE1YXQPbL+/v17ylerSduXL1+Ku1ofP3485bzGZyaLi4s9UjZ0lQChA/ph0i2t0RM8Smn2SR8r3eir/AGt9VcIQgdRP3To0Mr76vEtN33++OV6fmhefsHKW/XKnH/2vjmouSphCB3MPK/8ZonHm38kxHoTe9rso5SZR3B7tA5H6NYImw8wWjiadFUbyb4erm7jvzgyIrEezr151dbHEYQeuE6TrnD5lEbvsdfiqvgkkUt46zBwK3QSntCdYGw3yKT71tUR18pVO68D5Ac5jM8s8vnlP0tLS+1AOLo1AUK3RtjtANOmseNRou7tTptBVM/HFLvbHmgzGqHb0Ovx2Gkrx9NCVh9kP2nBrY9TdVuqD6rtxiR0O369Hz263TUSNkrWSYmNpv75HLZt25YeP37ce/4CNCNA6Ga8Bt+7zhS4r5PMC3T5E2W2tUuA0Gu3No3ObPTeuzr1bjTAlJ3z1dh75C5IxoxB6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQIHQIZkEQiCFA6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQ+A+sTBEnEQXhEgAAAABJRU5ErkJggg==", - mimeType: "image/png", - }, - }, - ], - }, - }, - path: [2], - timestamp: 16797.5, - bubbled: false, - }, - async reply() {}, - }, - { - type: "nodeend", - data: { - node: { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - content: { - role: "user", - parts: [ - { - inlineData: { - data: "iVBORw0KGgoAAAANSUhEUgAAAPQAAAC3CAYAAAAl43M8AAAAAXNSR0IArs4c6QAACb1JREFUeF7t3buO1EwTgOGGRURIcAEEcAecxSkjJOAQEBBwA0gQkAESISIn5wKAjBCEkBDitAtCIiQDcQmc2U+9+md/M8ww9tgu7/Y+lhBasLtcb9U77mnveDYtLy8vJxsCCBRBYBOhi6ijJBBYIUBojYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVMxpqezbty9t3rw5LS8vr+yS/379+vXKv9nKIkDoNVDP27dvpzt37qzKloV78+ZNJ2c2knnSYNu3b0+PHj3qJI5B1gYBQq+BOuzfvz9t2rTpjzPJUi8uLrY+u38J/fv377S0tNQ6hgHWDgFCD1yLAwcOTDyDLmTLMucXitGLxWjKXf25ixeNgREKXyFA6IHbYZrQXVyhx6/8CwsL6efPn3/MBvJ7aVs5BAg9cC0nTbfzKXVxhZ42djVlQg/cAB2HJ3THQJsON+0KvWvXrnTv3r2mw/2x//iUu/qfXcwAWp2cg3shQOhesNYf9PDhwyvT4NGWRct/ulqs2rt378rtqeqiWx7/x48f6d27d/VP1J7rggChBy7T58+f08mTJ1cXr379+tXZLauBUxN+AAKEHgC6kAj0RYDQfZE1LgIDECD0ANCFRKAvAoTui6xxERiAAKEHgC4kAn0RIHRfZI2LwAAECD0AdCER6IsAofsia1wEBiBA6AGgC4lAXwQI3RdZ4yIwAAFCDwBdSAT6IkDoGWTPnTuXPnz4sLJX/j3rt2/f9lUL4yLQmgChZyCsPsLHRw5b95sBeiZA6BmAqw8JIHTP3Wj41gQI7QrduomaDPDx48e0c+fOJofYtwEBQhO6Qbu02/XKlSvpyZMnaevWrenZs2ftBnP0RAKEbiB03tUzuOY3qfq4pevXr6fTp0/PP5gjCT1PD1gUm4fa5GOq6xH50Uv5CwZs3RJwhbYo1m1H/WO0qtC7d+9Od+/eDYu9UQIRmtBhvV6dcp85cyZdu3YtLPZGCUToGZW+ceNGevDgwepTMz3Ebz41Tp06lT59+rR6sLWI+TjOOorQswillNyLrgHJTKc9pA5GIHQNiONCnz9/PuVbMLb6BKrTbb+gU59b0z0JXZNYVeouvqamZthidqvyyw/9f/XqVTG5raVECF2zGuPfE3Xp0qV04cKFmkdv7N2OHDmy8k0do+3s2bPp6tWrGxtKT9kTuibY8a+UcZWuCS6ldPDgwZWv9xltFsTqs2u6J6EbEBu/Slvxrgdv/Av5CF2P2zx7EboBtZs3b6b79++vHmFxpx48C2L1OHWxF6EbUqz+KqgpZD14VaG9VanHbN69CD0HufGpd/661pcvX84x0sY4pMprx44d6eHDhxsj8QGyJPQc0MeFNvWeDtGC2BwN1uIQQs8Jb3yhxwLZZJAWxOZssDkPI/Sc4PJhpt6z4VkQm82oyz0I3YJmvje9sLDwxwi3bt1KJ06caDFqWYe6QsfWk9AteY83bB7Ofdb/Q3WFbtlgDQ8ndENgk3Yfv5Xl1sxkob3QddBsM4YgdEeMx99Pu1L/vcZA6I6a7R/DELojxk+fPk2XL19efRBCHnaj385yy6qj5mowDKEbwJq16/Pnz9PFixdJ/T9QFsRmdUz3/0/ojpnu2bMnbdmy5a9RN+J004JYx81VYzhC14DUdJc81cwLY/mD/KMtT7+/fv2a3r9/33S4dbf/0aNH07dv3/7IfyO+oA1ROEL3RH3SPeosdb56v3jxoqeoww977NixlReu6ouZJ5TE1YXQPbL+/v17ylerSduXL1+Ku1ofP3485bzGZyaLi4s9UjZ0lQChA/ph0i2t0RM8Smn2SR8r3eir/AGt9VcIQgdRP3To0Mr76vEtN33++OV6fmhefsHKW/XKnH/2vjmouSphCB3MPK/8ZonHm38kxHoTe9rso5SZR3B7tA5H6NYImw8wWjiadFUbyb4erm7jvzgyIrEezr151dbHEYQeuE6TrnD5lEbvsdfiqvgkkUt46zBwK3QSntCdYGw3yKT71tUR18pVO68D5Ac5jM8s8vnlP0tLS+1AOLo1AUK3RtjtANOmseNRou7tTptBVM/HFLvbHmgzGqHb0Ovx2Gkrx9NCVh9kP2nBrY9TdVuqD6rtxiR0O369Hz263TUSNkrWSYmNpv75HLZt25YeP37ce/4CNCNA6Ga8Bt+7zhS4r5PMC3T5E2W2tUuA0Gu3No3ObPTeuzr1bjTAlJ3z1dh75C5IxoxB6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQIHQIZkEQiCFA6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQ+A+sTBEnEQXhEgAAAABJRU5ErkJggg==", - mimeType: "image/png", - }, - }, - ], - }, - }, - validatorMetadata: [], - path: [2], - timestamp: 16803.69999998808, - outputs: {}, - }, - async reply() {}, - }, - { type: "graphend", data: { path: [], timestamp: 16807 }, async reply() {} }, -]; diff --git a/packages/breadboard/tests/inspector/node.ts b/packages/breadboard/tests/inspector/node.ts deleted file mode 100644 index 25f2b987ec9..00000000000 --- a/packages/breadboard/tests/inspector/node.ts +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { inspectableGraph } from "../../src/inspector/graph.js"; -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; - -test("inspectableNode correctly returns node configuration", (t) => { - const graph = { - nodes: [ - { - id: "a", - type: "foo", - configuration: { - foo: "test", - }, - }, - ], - edges: [], - }; - const inspectable = inspectableGraph(graph); - t.deepEqual(inspectable.nodeById("a")?.configuration(), { foo: "test" }); -}); - -test("inspectableNode correctly returns node title", (t) => { - { - const graph = { - nodes: [ - { - id: "a", - type: "foo", - }, - ], - edges: [], - }; - const inspectable = inspectableGraph(graph); - t.deepEqual(inspectable.nodeById("a")?.title(), "a"); - } - { - const graph = { - nodes: [ - { - id: "a", - type: "foo", - metadata: { - title: "test", - }, - }, - ], - edges: [], - }; - const inspectable = inspectableGraph(graph); - t.deepEqual(inspectable.nodeById("a")?.title(), "test"); - } -}); - -test("InspectableNode instances are stable within InspectableGraph", (t) => { - const graph = { - nodes: [ - { - id: "a", - type: "foo", - }, - { - id: "b", - type: "bar", - }, - ], - edges: [{ from: "a", to: "b" }], - }; - const inspectable = inspectableGraph(graph); - t.assert(inspectable.nodeById("a") === inspectable.nodeById("a")); - t.assert(inspectable.nodeById("b") === inspectable.nodeById("b")); - t.assert(inspectable.nodeById("a") === inspectable.entries()[0]); - t.assert(inspectable.nodesByType("foo")[0] === inspectable.nodeById("a")); -}); - -test("A graph with no nodes doesn't cause errors", (t) => { - const graph = { - nodes: [], - edges: [], - }; - const inspectable = inspectableGraph(graph); - t.deepEqual(inspectable.nodes(), []); - t.deepEqual(inspectable.nodeById("a"), undefined); - t.deepEqual(inspectable.nodesByType("foo"), []); -}); - -test("A graph with start tags is correctly interpreted", (t) => { - const graph = { - nodes: [ - { - id: "a", - type: "foo", - metadata: { - tags: ["start"], - }, - }, - { - id: "b", - type: "bar", - metadata: { - tags: [{ type: "start", label: "describe" }], - }, - }, - ], - edges: [], - } as GraphDescriptor; - const inspectable = inspectableGraph(graph); - const a = inspectable.nodeById("a"); - t.deepEqual(a?.startLabels(), ["default"]); - t.is(a?.isEntry(), true); - t.is(a?.isEntry("default"), true); - t.is(a?.isEntry("describe"), false); - const b = inspectable.nodeById("b"); - t.deepEqual(b?.startLabels(), ["describe"]); - t.is(b?.isEntry("default"), false); - t.is(b?.isEntry("describe"), true); - - t.deepEqual( - inspectable.entries().map((n) => n.descriptor.id), - ["a"] - ); - t.deepEqual( - inspectable.entries("default").map((n) => n.descriptor.id), - ["a"] - ); - t.deepEqual( - inspectable.entries("describe").map((n) => n.descriptor.id), - ["b"] - ); -}); diff --git a/packages/breadboard/tests/inspector/observer-load.ts b/packages/breadboard/tests/inspector/observer-load.ts deleted file mode 100644 index 0aba12b40d9..00000000000 --- a/packages/breadboard/tests/inspector/observer-load.ts +++ /dev/null @@ -1,190 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { ExecutionContext } from "ava"; -import { readFile } from "fs/promises"; -import { join } from "path"; -import { - InspectableRun, - InspectableRunEvent, - InspectableRunObserver, -} from "../../src/inspector/types.js"; -import { createRunObserver } from "../../src/index.js"; -import { HarnessRunResult } from "../../src/harness/types.js"; -import { replaceSecrets } from "../../src/inspector/run/serializer.js"; -import { - createDefaultDataStore, - createDefaultRunStore, -} from "../../src/data/index.js"; - -const BASE_PATH = new URL( - "../../../tests/inspector/data/loader", - import.meta.url -).pathname; - -const loadRawRun = async ( - observer: InspectableRunObserver, - name: string -): Promise => { - const s = await readFile(join(BASE_PATH, name), "utf-8"); - const raw = JSON.parse(s) as HarnessRunResult[]; - for (const result of raw) { - await observer.observe(result); - } - - const runs = await observer.runs(); - return runs[0]; -}; - -const propsEqual = ( - t: ExecutionContext, - o1: Record, - o2: Record, - props: string[] -) => { - props.forEach((prop) => { - t.deepEqual(o1[prop], o2[prop], prop); - }); -}; - -const EVENT_PROPS = ["type", "start", "end", "bubbled", "hidden"]; -const NODE_PROPS = ["inputs", "outputs"]; -const RUN_PROPS = ["graphId", "graphVersion", "start", "end"]; - -const eventsEqual = ( - t: ExecutionContext, - events1: InspectableRunEvent[], - events2: InspectableRunEvent[] -) => { - t.is(events1.length, events2.length); - events1.forEach((event1, index) => { - const event2 = events2[index]; - t.truthy(event2); - propsEqual(t, event1, event2, EVENT_PROPS); - if (event1.type === "node" && event2.type === "node") { - propsEqual(t, event1, event2, NODE_PROPS); - event1.runs.forEach((run1, index) => { - const run2 = event2.runs[index]; - runsEqual(t, run1, run2); - }); - } - }); -}; - -const runsEqual = ( - t: ExecutionContext, - run1: InspectableRun, - run2: InspectableRun -) => { - propsEqual(t, run1, run2, RUN_PROPS); - eventsEqual(t, run1.events, run2.events); -}; - -const GEMINI_KEY_VALUE = "b576eea9-5ae6-4e9d-9958-e798ad8dbff7"; -const GEMINI_SENTINEL = "103e9083-13fd-46b4-a9ee-683a09e31a26"; - -test("run save/load: loadRawRun works as expected", async (t) => { - const observer = createRunObserver({ - logLevel: "debug", - }); - const run1 = await loadRawRun(observer, "ad-writer-2.1.raw.json"); - const run2 = await loadRawRun(observer, "ad-writer-2.1.raw.json"); - runsEqual(t, run1, run2); -}); - -test("run save/load: observer.save -> run.load roundtrip", async (t) => { - const observer = createRunObserver({ - logLevel: "debug", - dataStore: createDefaultDataStore(), - runStore: createDefaultRunStore(), - }); - const run1 = await loadRawRun(observer, "ad-writer-2.1.raw.json"); - if (!run1.serialize) { - t.fail("run1 should be serializable."); - return; - } - const run1serialized = await run1.serialize({ keepSecrets: true }); - const run1LoadResult = await observer.load(run1serialized); - if (!run1LoadResult.success) { - t.fail(run1LoadResult.error); - return; - } - runsEqual(t, run1, (await observer.runs())[0]); -}); - -test("run save/load: replaceSecrets correctly replaces secrets", async (t) => { - const observer = createRunObserver({ - logLevel: "debug", - }); - const run1 = await loadRawRun(observer, "ad-writer-2.1.raw.json"); - if (!run1.serialize) { - t.fail("run1 should be serializable."); - return; - } - - { - const run1withoutSecrets = await run1.serialize(); - const sentinel = run1withoutSecrets.secrets?.["GEMINI_KEY"]; - t.not(sentinel, GEMINI_KEY_VALUE); - const s = JSON.stringify(run1withoutSecrets); - t.false(s.includes(GEMINI_KEY_VALUE)); - const sentinelCount = (s.match(new RegExp(sentinel!, "g")) || []).length; - t.is(sentinelCount, 21); - } - - { - const run1withSecrets = await run1.serialize({ keepSecrets: true }); - - // replace secrets with sentinel values. - const elidedSecrets = replaceSecrets(run1withSecrets, (secret, value) => { - t.is(secret, "GEMINI_KEY"); - t.is(value, GEMINI_KEY_VALUE); - return GEMINI_SENTINEL; - }); - const sentinel = elidedSecrets.secrets?.["GEMINI_KEY"]; - t.is(sentinel, GEMINI_SENTINEL); - const s = JSON.stringify(elidedSecrets); - t.false(s.includes(GEMINI_KEY_VALUE)); - const sentinelCount = (s.match(new RegExp(sentinel!, "g")) || []).length; - t.is(sentinelCount, 21); - - // now, let's replace it back. - const withSecrets = replaceSecrets(elidedSecrets, (secret) => { - t.is(secret, "GEMINI_KEY"); - return GEMINI_KEY_VALUE; - }); - const s2 = JSON.stringify(withSecrets); - t.false(s2.includes(GEMINI_SENTINEL)); - const secretCount = (s2.match(new RegExp(GEMINI_KEY_VALUE, "g")) || []) - .length; - t.is(secretCount, 21); - } -}); - -test("run load/save: serialization produces consistent size", async (t) => { - const observer = createRunObserver({ - logLevel: "debug", - dataStore: createDefaultDataStore(), - runStore: createDefaultRunStore(), - skipDataStore: true, - }); - const run = await loadRawRun(observer, "ad-writer-2.1.raw.json"); - if (!run.serialize) { - t.fail("run1 should be serializable."); - return; - } - const serializedRun = await run.serialize(); - const s = JSON.stringify(serializedRun); - t.is(s.length, 1167746); - t.true( - ( - await observer.load(serializedRun, { - secretReplacer: () => GEMINI_KEY_VALUE, - }) - ).success - ); - runsEqual(t, run, (await observer.runs())[0]); -}); diff --git a/packages/breadboard/tests/inspector/ports.ts b/packages/breadboard/tests/inspector/ports.ts deleted file mode 100644 index cab865cdc46..00000000000 --- a/packages/breadboard/tests/inspector/ports.ts +++ /dev/null @@ -1,198 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; -import { inspectableGraph } from "../../src/inspector/graph.js"; -import { PortType } from "../../src/inspector/ports.js"; -import { Schema } from "../../src/types.js"; - -test("collectPorts correctly reports edges", async (t) => { - const graph = { - nodes: [ - { id: "a", type: "input" }, - { id: "b", type: "bar" }, - { id: "c", type: "output" }, - { id: "d", type: "baz" }, - ], - edges: [ - { from: "a", to: "b", in: "foo", out: "text" }, - { from: "d", to: "b", in: "foo", out: "baz" }, - { from: "b", to: "c", in: "text", out: "bar" }, - ], - } satisfies GraphDescriptor; - const inspectable = inspectableGraph(graph); - const b = inspectable.nodeById("b"); - const ports = await b?.ports(); - const inputs = ports?.inputs?.ports; - const outputs = ports?.outputs?.ports; - t.deepEqual( - inputs?.flatMap((p) => - p.edges?.map((e) => { - return { - in: e.in, - out: e.out, - from: e.from.descriptor.id, - to: e.to.descriptor.id, - }; - }) - ), - [ - { in: "foo", out: "text", from: "a", to: "b" }, - { in: "foo", out: "baz", from: "d", to: "b" }, - ] - ); - t.deepEqual( - outputs?.flatMap((p) => - p.edges?.map((e) => { - return { - in: e.in, - out: e.out, - from: e.from.descriptor.id, - to: e.to.descriptor.id, - }; - }) - ), - [{ in: "text", out: "bar", from: "b", to: "c" }] - ); -}); - -test("collectPorts correctly recognizes dangling ports", async (t) => { - const graph = { - nodes: [{ id: "a", type: "input" }], - edges: [{ from: "a", to: "a", in: "foo", out: "text" }], - } satisfies GraphDescriptor; - const inspectable = inspectableGraph(graph); - const a = inspectable.nodeById("a"); - const ports = await a?.ports(); - t.assert(ports?.inputs?.fixed); - const inputs = ports?.inputs?.ports; - t.deepEqual( - inputs?.map((p) => ({ name: p.name, status: p.status })), - [ - { name: "", status: "ready" }, - { name: "*", status: "ready" }, - { name: "foo", status: "dangling" }, - { name: "schema", status: "ready" }, - ] - ); -}); - -test("collectPorts adds an $error port", async (t) => { - const graph = { - nodes: [{ id: "a", type: "bar" }], - edges: [], - } satisfies GraphDescriptor; - const inspectable = inspectableGraph(graph); - const a = inspectable.nodeById("a"); - const ports = await a?.ports(); - const outputs = ports?.outputs?.ports; - t.deepEqual( - outputs?.map((p) => ({ name: p.name, status: p.status })), - [ - { name: "", status: "ready" }, - { name: "$error", status: "ready" }, - { name: "*", status: "ready" }, - ] - ); -}); - -test("PortType correctly recognizes unknown types", (t) => { - const from = new PortType({}); - const notTo = new PortType({ type: "object" }); - const to = new PortType({}); - const specificFrom = new PortType({ type: "number" }); - t.true(from.canConnect(to)); - t.false(from.canConnect(notTo)); - t.true(specificFrom.canConnect(to)); -}); - -test("PortType matches strings, numbers, and booleans", (t) => { - { - const from = new PortType({ type: "string" }); - const to = new PortType({ type: "string" }); - const notTo = new PortType({ type: "number" }); - t.true(from.canConnect(to)); - t.false(from.canConnect(notTo)); - } - { - const from = new PortType({ type: "number" }); - const to = new PortType({ type: "number" }); - const notTo = new PortType({ type: "string" }); - t.true(from.canConnect(to)); - t.false(from.canConnect(notTo)); - } -}); - -test("PortType matches behaviors", (t) => { - const from = new PortType({ type: "object", behavior: ["llm-content"] }); - const to = new PortType({ type: "object", behavior: ["llm-content"] }); - const alsoTo = new PortType({ - type: "object", - behavior: ["llm-content", "deprecated"], - }); - t.true(from.canConnect(to)); - t.true(from.canConnect(alsoTo)); -}); - -test("PortType matches formats", (t) => { - const audioOnly = new PortType({ - type: "object", - behavior: ["llm-content"], - format: "audio-file", - } satisfies Schema); - const any = new PortType({ type: "object", behavior: ["llm-content"] }); - const imageOnly = new PortType({ - type: "object", - behavior: ["llm-content"], - format: "image-file", - } satisfies Schema); - const audioAndImage = new PortType({ - type: "object", - behavior: ["llm-content"], - format: "audio-file,image-file", - } satisfies Schema); - t.true(audioOnly.canConnect(audioOnly)); - t.false(audioOnly.canConnect(imageOnly)); - t.false(audioAndImage.canConnect(imageOnly)); - // TODO(aomarks) Disabled because this is not compatible with - // analyzeIsJsonSubSchema, which treats each format as distinct and doesn't - // support the comma-delimited format. I think we should just be using `anyOf` - // here if we want to make a union of multiple formats. See also - // https://json-schema.org/understanding-json-schema/reference/non_json_data - // which is how JSON Schema itself represents non-JSON data which we should - // consider migrating to. - // t.true(imageOnly.canConnect(audioAndImage)); - t.true(audioOnly.canConnect(any)); - t.false(any.canConnect(audioOnly)); -}); - -test("PortType handles arrays", (t) => { - const audioOnly = new PortType({ - type: "array", - items: { - type: "object", - behavior: ["llm-content"], - format: "audio-file", - }, - } satisfies Schema); - const any = new PortType({ - type: "array", - items: { type: "object", behavior: ["llm-content"] }, - } satisfies Schema); - - t.true(audioOnly.canConnect(any)); - t.false(any.canConnect(audioOnly)); - - const numbers = new PortType({ - type: "array", - items: { type: "number" }, - }); - t.false(numbers.canConnect(any)); - t.false(audioOnly.canConnect(numbers)); - t.true(numbers.canConnect(numbers)); -}); diff --git a/packages/breadboard/tests/inspector/schemas.ts b/packages/breadboard/tests/inspector/schemas.ts deleted file mode 100644 index 6bfe25b0ceb..00000000000 --- a/packages/breadboard/tests/inspector/schemas.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { inspectableGraph } from "../../src/inspector/graph.js"; - -test("input in ports are fixed", async (t) => { - const graph = inspectableGraph({ - nodes: [ - { - id: "node", - type: "input", - }, - ], - edges: [], - }); - const node = graph.nodeById("node"); - const ports = await node?.ports(); - t.true(ports?.inputs.fixed); -}); - -test("output out ports are fixed", async (t) => { - const graph = inspectableGraph({ - nodes: [ - { - id: "node", - type: "output", - }, - ], - edges: [], - }); - const node = graph.nodeById("node"); - const ports = await node?.ports(); - t.true(ports?.outputs.fixed); -}); diff --git a/packages/breadboard/tests/inspector/subgraphs.ts b/packages/breadboard/tests/inspector/subgraphs.ts deleted file mode 100644 index 6f215fbe9c7..00000000000 --- a/packages/breadboard/tests/inspector/subgraphs.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; -import test from "ava"; -import { inspectableGraph } from "../../src/inspector/graph.js"; - -test("InspectableGraph correctly provides subgraphs", async (t) => { - const graph: GraphDescriptor = { - nodes: [], - edges: [], - graphs: { - "#foo": { - nodes: [{ id: "a", type: "foo" }], - edges: [], - }, - }, - }; - - const inspectable = inspectableGraph(graph); - const graphs = inspectable.graphs(); - - t.is(Object.values(graphs).length, 1); - t.true(graphs === inspectable.graphs()); - const subgraph = graphs["#foo"]; - t.truthy(subgraph); - const node = subgraph.nodeById("a"); - t.truthy(node); - t.is(node?.descriptor.type, "foo"); -}); diff --git a/packages/breadboard/tests/inspector/traversal.ts b/packages/breadboard/tests/inspector/traversal.ts deleted file mode 100644 index ac7442bd7a8..00000000000 --- a/packages/breadboard/tests/inspector/traversal.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -// These test traversal of the inspector API. - -import test from "ava"; -import { inspectableGraph } from "../../src/inspector/graph.js"; -import { createLoader } from "../../src/loader/index.js"; - -const BASE_URL = new URL("../../../tests/inspector/data/", import.meta.url); - -const load = async (url: string) => { - const base = BASE_URL; - const loader = createLoader(); - const result = await loader.load(url, { base }); - if (!result) return undefined; - return inspectableGraph(result); -}; - -test("inspector API can traverse simplest.json", async (t) => { - const simplest = await load("simplest.json"); - // This is mostly to avoid needing to do `graph?` everywhere. - if (!simplest) { - return t.fail("Graph is undefined"); - } - t.assert(simplest.nodes().length == 3, "The graph has three nodes"); - - const entries = simplest.entries(); - t.assert(entries.length == 1, "The graph has one entry"); - - const input = entries[0]; - t.assert(input.descriptor.type == "input", "The entry is an input"); - - const fromInput = input.outgoing(); - t.assert(fromInput.length == 1, "The input has one outgoing edge"); - - const invoke = fromInput[0].to; - t.assert(invoke.descriptor.type == "invoke", "The next node is an invoke"); - - const fromInvoke = invoke.outgoing(); - t.assert(fromInvoke.length == 1, "The invoke has one outgoing edge"); - - const output = fromInvoke[0].to; - t.assert(output.descriptor.type == "output", "The next node is an output"); - t.assert(output.isExit(), "The output is an exit node"); -}); diff --git a/packages/breadboard/tests/kits.ts b/packages/breadboard/tests/kits.ts deleted file mode 100644 index 925b32d7db7..00000000000 --- a/packages/breadboard/tests/kits.ts +++ /dev/null @@ -1,268 +0,0 @@ -import test from "ava"; -import { KitBuilder } from "../src/kits/builder.js"; -import { Board } from "../src/board.js"; -import { invokeGraph } from "../src/index.js"; - -test("KitBuilder can wrap a function", async (t) => { - // A normal function that will be wrapped. - const echo = (input: string) => input; - const test = (input: string) => input; - - const MyKit = KitBuilder.wrap({ url: "test" }, { echo, test }); - - const board = new Board({ - title: "Test Echo", - description: "Test Breadboard Kit", - version: "0.0.1", - }); - - const myKit = board.addKit(MyKit); - - t.true(myKit.echo instanceof Function); - t.true(myKit.test instanceof Function); -}); - -test("KitBuilder can call a function that returns a string", async (t) => { - // A normal function that will be wrapped. - const echo = (echo_this: string) => echo_this; - - const MyKit = KitBuilder.wrap({ url: "test" }, { echo }); - - const board = new Board({ - title: "Test Echo", - description: "Test Breadboard Kit", - version: "0.0.1", - }); - - const myKit = board.addKit(MyKit); - - const input = board.input(); - const echoNode = myKit.echo(); - - input.wire("an_input->echo_this", echoNode); - // result because it's just a string from a dynamic function - echoNode.wire("result->an_output", board.output()); - - const output = await invokeGraph( - board, - { - an_input: "hello world", - }, - { kits: [myKit] } - ); - - t.is(output["an_output"], "hello world"); -}); - -test("KitBuilder can call a function that returns an object", async (t) => { - // A normal function that will be wrapped. - const echo = (echo_this: string) => { - return { out: echo_this, other: "stuff" }; - }; - - const MyKit = KitBuilder.wrap({ url: "test" }, { echo }); - - const board = new Board({ - title: "Test Echo", - description: "Test Breadboard Kit", - version: "0.0.1", - }); - - const myKit = board.addKit(MyKit); - - const input = board.input(); - const echoNode = myKit.echo(); - - input.wire("an_input->echo_this", echoNode); - // result because it's just a string from a dynamic function - echoNode.wire("out->an_output", board.output()); - - const output = await invokeGraph( - board, - { - an_input: "hello world", - }, - { kits: [myKit] } - ); - - t.is(output["an_output"], "hello world"); -}); - -test("KitBuilder can call a function that has more than one input", async (t) => { - // A normal function that will be wrapped. - const add = (a: number, b: number) => { - return a + b; - }; - - const MyKit = KitBuilder.wrap({ url: "test" }, { add }); - - const board = new Board({ - title: "Test Echo", - description: "Test Breadboard Kit", - version: "0.0.1", - }); - - const myKit = board.addKit(MyKit); - - const inputA = board.input(); - const inputB = board.input(); - - const addNode = myKit.add(); - - inputA.wire("a->a", addNode); - inputB.wire("b->b", addNode); - // result because it's just a string from a dynamic function - addNode.wire("result->", board.output()); - - const output = await invokeGraph( - board, - { - a: 1, - b: 2, - }, - { kits: [myKit] } - ); - - t.is(output["result"], 3); -}); - -test("KitBuilder can call a function from an external import", async (t) => { - const js = await import("jsonschema"); - - // Wrap the jsonschema validate function in a kit and expose function as a node. - const MyKit = KitBuilder.wrap( - { url: "test" }, - { validate: js.default.validate } - ); - - const board = new Board({ - title: "Test Echo", - description: "Test Breadboard Kit", - version: "0.0.1", - }); - - const myKit = board.addKit(MyKit); - - const inputA = board.input(); - const inputB = board.input(); - const inputC = board.input(); - - const validateNode = myKit.validate(); - - inputA.wire("a->instance", validateNode); - inputB.wire("b->schema", validateNode); - inputC.wire("c->options", validateNode); - - // result because it's just a string from a dynamic function - validateNode.wire("errors->", board.output()); - - const output = await invokeGraph( - board, - { - a: { hello: "world" }, - b: { type: "object" }, - c: { allowUnknownAttributes: true }, - }, - { kits: [myKit] } - ); - - const result = js.default.validate( - { hello: "world" }, - { type: "object" }, - { allowUnknownAttributes: true } - ); - - t.is((>output["errors"]).length, result.errors.length); -}); - -test("KitBuilder can splat all the functions in the external library and make nodes", async (t) => { - const js = await import("jsonschema"); - - // Wrap the jsonschema validate function in a kit and expose function as a node. - const MyKit = KitBuilder.wrap({ url: "test" }, { ...js.default }); - - const board = new Board({ - title: "Test Echo", - description: "Test Breadboard Kit", - version: "0.0.1", - }); - - const myKit = board.addKit(MyKit); - - myKit.validate(); - - // We really need to pick a library with more than one function. - t.true(myKit.validate instanceof Function); -}); - -test("KitBuilder can access platform functions", async (t) => { - // Wrap the jsonschema validate function in a kit and expose function as a node. - const MyKit = KitBuilder.wrap({ url: "test" }, { random: Math.random }); - - const board = new Board({ - title: "Test Echo", - description: "Test Breadboard Kit", - version: "0.0.1", - }); - - const myKit = board.addKit(MyKit); - - myKit.random(); - - // We really need to pick a library with more than one function. - t.true(myKit.random instanceof Function); -}); - -test("KitBuilder can call platform functions that contain 0 arguments", async (t) => { - // Wrap the jsonschema validate function in a kit and expose function as a node. - const MyKit = KitBuilder.wrap({ url: "test" }, { random: Math.random }); - - const board = new Board({ - title: "Test Echo", - description: "Test Breadboard Kit", - version: "0.0.1", - }); - - const myKit = board.addKit(MyKit); - - const random = myKit.random(); - - // result because it's just a string from a dynamic function - random.wire("result->", board.output()); - - const output = await invokeGraph(board, {}, { kits: [myKit] }); - - // We really need to pick a library with more than one function. - t.true(typeof output["result"] === "number"); -}); - -test("KitBuilder can call platform functions that accept a splat", async (t) => { - // Wrap the jsonschema validate function in a kit and expose function as a node. - const MyKit = KitBuilder.wrap({ url: "test" }, { min: Math.min }); - - const board = new Board({ - title: "Test Echo", - description: "Test Breadboard Kit", - version: "0.0.1", - }); - - const myKit = board.addKit(MyKit); - - const min = myKit.min(); - const input = board.input(); - - // result because it's just a string from a dynamic function - input.wire("___args->", min.wire("result->", board.output())); - - const output = await invokeGraph( - board, - { - ___args: [1, 2, 3, 4, 5], - }, - { kits: [myKit] } - ); - - // We really need to pick a library with more than one function. - t.true(typeof output["result"] === "number"); - t.true(output["result"] === 1); -}); diff --git a/packages/breadboard/tests/loader/loader.ts b/packages/breadboard/tests/loader/loader.ts deleted file mode 100644 index 51aefff80f6..00000000000 --- a/packages/breadboard/tests/loader/loader.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { - SENTINEL_BASE_URL, - baseURLFromContext, -} from "../../src/loader/loader.js"; -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; - -test("relativeBasePath is relative to invoking board", (t) => { - t.is( - baseURLFromContext({ - board: { url: "http://bar" } as GraphDescriptor, - }).href, - "http://bar/" - ); - t.is( - baseURLFromContext({ - board: {} as GraphDescriptor, - base: new URL("http://baz"), - }).href, - "http://baz/" - ); -}); - -test("relativeBasePath falls back to explicit option", (t) => { - t.deepEqual( - baseURLFromContext({ - board: { url: "file:///bar/foo" } as GraphDescriptor, - base: new URL("http://baz"), - }).href, - "file:///bar/foo" - ); -}); - -test("relativeBasePath falls back to SENTINEL_BASE_URL", (t) => { - t.is(baseURLFromContext({}).href, SENTINEL_BASE_URL.href); -}); diff --git a/packages/breadboard/tests/machine.ts b/packages/breadboard/tests/machine.ts deleted file mode 100644 index cd2227530c6..00000000000 --- a/packages/breadboard/tests/machine.ts +++ /dev/null @@ -1,172 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { readFile, readdir } from "fs/promises"; - -import { TraversalMachine } from "../src/index.js"; - -import { - ErrorCapability, - GraphDescriptor, - InputValues, - OutputValues, -} from "../src/types.js"; -import { MachineResult } from "../src/traversal/result.js"; -import { StartLabel } from "@google-labs/breadboard-schema/graph.js"; - -const IN_DIR = "./tests/data/"; - -interface TestGraphDescriptor extends GraphDescriptor { - sequence: string[]; - inputs: InputValues; - outputs: OutputValues[]; - throws: boolean; - start: StartLabel; -} - -const graphs = (await readdir(`${IN_DIR}/`)).filter((file) => - file.endsWith(".json") -); - -await Promise.all( - graphs.map(async (filename) => { - test(filename, async (t) => { - const data = await readFile(`${IN_DIR}${filename}`, "utf-8"); - const graph = JSON.parse(data) as TestGraphDescriptor; - if (graph.title?.includes("skip")) { - t.pass(); - t.log("Skipped"); - return; - } - const machine = new TraversalMachine(graph, undefined, graph.start); - const outputs: OutputValues[] = []; - const sequence: string[] = []; - const run = async () => { - for await (const result of machine) { - if (result.skip) continue; - const { inputs, descriptor } = result; - sequence.push(descriptor.id); - switch (descriptor.type) { - case "input": - result.outputs = graph.inputs; - break; - case "output": - outputs.push({ ...inputs }); - break; - case "extract": { - const list = result.inputs.list as string[]; - const text = list.shift(); - result.outputs = list.length ? { list, text } : { text }; - break; - } - case "make": { - // A node that creates its own output. - result.outputs = { text: "Hello, world!" }; - break; - } - case "error": { - result.outputs = { - $error: { - kind: "error", - error: new Error("Test error"), - } as ErrorCapability, - }; - break; - } - case "noop": - result.outputs = { ...inputs }; - break; - default: - throw new Error(`Unknown node: ${descriptor.id}`); - } - } - }; - if (graph.throws) { - await t.throwsAsync(run); - } else { - await run(); - } - - // Rewrite instances of Error to strings for comparison. - outputs.forEach((output) => { - if (output.$error) { - const $error = output.$error as ErrorCapability; - if ($error.error) { - t.true($error.error instanceof Error); - output.$error = { ...$error, error: "instanceof Error" }; - } - } - }); - - t.deepEqual(outputs, graph.outputs); - t.deepEqual(sequence, graph.sequence); - }); - }) -); - -test("Can be interrupted and resumed", async (t) => { - const data = await readFile(`${IN_DIR}one-entry.json`, "utf-8"); - const graph = JSON.parse(data) as TestGraphDescriptor; - let result: MachineResult; - - // First iteration. - { - const machine = new TraversalMachine(graph); - const iterator = machine.start(); - const iteratorResult = await iterator.next(); - result = iteratorResult.value; - const { descriptor, skip } = iteratorResult.value; - t.false(skip); - t.false(iteratorResult.done); - t.like(descriptor, { - id: "node-a", - type: "input", - }); - result.outputs = graph.inputs; - } - - // Second iteration. - { - const machine = new TraversalMachine(graph, result); - const iterator = machine.start(); - const iteratorResult = await iterator.next(); - result = iteratorResult.value; - const { skip } = iteratorResult.value; - t.true(skip); - } - - // Third iteration. - { - const machine = new TraversalMachine(graph, result); - const iterator = machine.start(); - const iteratorResult = await iterator.next(); - result = iteratorResult.value; - const { descriptor, skip } = iteratorResult.value; - t.false(skip); - t.like(descriptor, { - id: "node-b", - type: "noop", - }); - result.outputs = result.inputs; - } - - // Fourth iteration. - { - const machine = new TraversalMachine(graph, result); - const iterator = machine.start(); - const iteratorResult = await iterator.next(); - result = iteratorResult.value; - const { descriptor } = iteratorResult.value; - t.like(descriptor, { - id: "node-c", - type: "output", - }); - } - - t.deepEqual(result.inputs, graph.outputs[0]); -}); diff --git a/packages/breadboard/tests/new/grammar/board-as-code.ts b/packages/breadboard/tests/new/grammar/board-as-code.ts deleted file mode 100644 index 3c591a3b6f1..00000000000 --- a/packages/breadboard/tests/new/grammar/board-as-code.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { code } from "../../../src/index.js"; - -test("`code` works with sync arrow functions", async (t) => { - const fn = await code(() => { - return { value: 1 }; - })({ $id: "fn" }).serialize(); - t.like(fn, { - nodes: [ - { - type: "runJavascript", - configuration: { - code: `const fn = () => { - return { value: 1 }; - };`, - }, - }, - ], - }); -}); - -test("`code` works with sync arrow return-less functions", async (t) => { - // prettier-ignore - const fn = await code(({context}) => context ? { context } : { context: null })({ - $id: "fn", - }).serialize(); - t.like(fn, { - nodes: [ - { - type: "runJavascript", - configuration: { - code: `const fn = ({ context }) => context ? { context } : { context: null };`, - }, - }, - ], - }); -}); - -test("`code` works with async arrow functions", async (t) => { - const fn = await code(async () => { - return { value: 1 }; - })({ $id: "fn" }).serialize(); - t.like(fn, { - nodes: [ - { - type: "runJavascript", - configuration: { - code: `const fn = async () => { - return { value: 1 }; - };`, - }, - }, - ], - }); -}); diff --git a/packages/breadboard/tests/new/grammar/board-overloads.ts b/packages/breadboard/tests/new/grammar/board-overloads.ts deleted file mode 100644 index 1e24c940b70..00000000000 --- a/packages/breadboard/tests/new/grammar/board-overloads.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { board, code } from "../../../src/new/grammar/board.js"; - -test("schema + graph, w/ nested code board", async (t) => { - const graph = board( - { - input: { - type: "object", - properties: { - foo: { - type: "string", - }, - }, - }, - output: { - type: "object", - properties: { - foo: { - type: "string", - }, - }, - }, - }, - (inputs) => { - return code(({ foo }) => ({ foo: `${foo}!` }))(inputs); - } - ); - - const result = await graph({ foo: "bar" }); - t.like(result, { foo: "bar!" }); -}); - -test("board with its own inputs and outputs", async (t) => { - const graph = board((_, base) => { - base.input().foo.as("bar").to(base.output()); - }); - - const serialized = await graph.serialize(); - - t.like(serialized, { - nodes: [{ type: "input" }, { type: "output" }], - }); - - const result = await graph({ foo: "success" }); - t.like(result, { bar: "success" }); -}); diff --git a/packages/breadboard/tests/new/grammar/invoke-by-await.ts b/packages/breadboard/tests/new/grammar/invoke-by-await.ts deleted file mode 100644 index 5c37d202bde..00000000000 --- a/packages/breadboard/tests/new/grammar/invoke-by-await.ts +++ /dev/null @@ -1,271 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { board, code } from "../../../src/new/grammar/board.js"; -import { V } from "../../../src/index.js"; -import { testKit } from "../../helpers/_test-kit.js"; - -test("directly await a node", async (t) => { - const { foo } = await testKit.noop({ foo: "bar" }); - t.is(foo, "bar"); -}); - -test("directly await a value", async (t) => { - const foo = await testKit.noop({ foo: "bar" }).foo; - t.is(foo, "bar"); -}); - -test("directly await a value called 'to'", async (t) => { - const to = (await testKit.noop({ to: "foo" }).to) as unknown as string; - t.is(to, "foo"); -}); - -test("directly await declarative board returning node, value assignment", async (t) => { - const graph = board((inputs) => { - return testKit.noop({ foo: inputs.foo }); - }); - const foo = await graph({ foo: "bar" }).foo; - t.is(foo, "bar"); -}); - -test("directly await declarative board returning node, deconstruct", async (t) => { - const graph = board<{ foo: string }>((inputs) => { - return testKit.noop({ foo: inputs.foo }); - }); - const { foo } = await graph({ foo: "bar" }); - t.is(foo, "bar"); -}); - -test("directly await declarative board, value assignment", async (t) => { - const graph = board((inputs) => { - const { foo } = testKit.noop({ foo: inputs.foo }); - return { foo }; - }); - const foo = await graph({ foo: "bar" }).foo; - t.is(foo, "bar"); -}); - -test("directly await declarative board, values named 'in' and 'to'", async (t) => { - const graph = board<{ in: string }, { to: unknown }>((inputs) => { - const { to } = testKit.noop({ to: inputs.in }); - return { to: to as unknown as V }; - }); - const to = await graph({ in: "bar" }).to; - t.is(to, "bar"); -}); - -test("directly await declarative board, deconstruct", async (t) => { - const graph = board((inputs) => { - const { foo } = testKit.noop({ foo: inputs.foo }); - return { foo }; - }); - const { foo } = await graph({ foo: "bar" }); - t.is(foo as unknown as string, "bar"); -}); - -test("directly await declarative board, deconstruct, 'in' and 'to'", async (t) => { - const graph = board((inputs) => { - const { to } = testKit.noop({ to: inputs.in }); - return { to: to as unknown as V }; - }); - const { to } = await graph({ in: "bar" }); - t.is(to as unknown as string, "bar"); -}); - -test("directly await declarative board, passing full inputs, value", async (t) => { - const graph = board((inputs) => { - return testKit.noop(inputs); - }); - const baz = await graph({ baz: "bar" }).baz; - t.is(baz, "bar"); -}); - -test("directly await declarative board, passing full inputs, deconstruct", async (t) => { - const graph = board<{ [key: string]: unknown }>((inputs) => { - return testKit.noop(inputs); - }); - const { baz } = await graph({ baz: "bar" }); - t.is(baz, "bar"); -}); - -test("directly await declarative board, passing full inputs as spread", async (t) => { - const graph = board((inputs) => { - return testKit.noop({ ...inputs }); - }); - const baz = await graph({ baz: "bar" }).baz; - t.is(baz, "bar"); -}); - -test("directly await declarative board, passing full inputs as spread, twice", async (t) => { - const graph = board<{ [key: string]: string }>((inputs) => { - const reverser = testKit.reverser({ ...inputs }); - return testKit.noop({ ...reverser }); - }); - const baz = await graph({ baz: "bar" }).baz; - t.is(baz as unknown as string, "rab"); -}); - -test("directly await imperative board, value assignment", async (t) => { - const graph = code(async (inputs) => { - const { foo } = await testKit.noop({ foo: inputs.foo }); - return { foo }; - }); - const foo = await graph({ foo: "bar" }).foo; - t.is(foo, "bar"); -}); - -test("directly await imperative board, deconstruct", async (t) => { - const graph = code(async (inputs) => { - const { foo } = await testKit.noop({ foo: inputs.foo }); - return { foo }; - }); - const { foo } = await graph({ foo: "bar" }); - t.is(foo, "bar"); -}); - -test("if-else, imperative execution", async (t) => { - const math = code(async () => { - return { result: "math result" }; - }); - const search = code(async () => { - return { text: "search result" }; - }); - - const graph = board({ - input: { - type: "object", - required: ["question"], - properties: { - question: { - type: "string", - title: "Query", - description: "A math or search question?", - }, - }, - }, - output: { - type: "object", - required: ["result"], - properties: { - result: { - type: "string", - title: "Answer", - description: "The answer to the query", - }, - }, - }, - invoke: async (inputs) => { - const { text } = (await testKit - .noop({ - template: - "Is this question about math? Answer YES or NO.\nQuestion: {{question}}\nAnswer: ", - question: inputs.question, - }) - .question.as("text") - .to( - testKit.noop({ - PALM_KEY: testKit.noop({ PALM_KEY: "dummy" }).PALM_KEY, - }) - )) as { text: string }; - - if (text?.startsWith("YES")) { - return { - result: (await math({ question: inputs.question }).result) ?? "", - }; - } else { - return { - result: (await search({ text: inputs.question }).text) ?? "", - }; - } - }, - }); - - { - const { result } = await graph({ question: "YES it is" }); - t.is(result, "math result"); - } - - { - const { result } = await graph({ question: "NO it is" }); - t.is(result, "search result"); - } -}); - -test.skip("if-else, serializable", async (t) => { - const math = code(async () => { - return { result: "math result" }; - }); - const search = code(async () => { - return { text: "search result" }; - }); - - const graph = board( - { - input: { - type: "object", - required: ["question"], - properties: { - question: { - type: "string", - title: "Query", - description: "A math or search question?", - }, - }, - }, - output: { - type: "object", - required: ["result"], - properties: { - result: { - type: "string", - title: "Answer", - description: "The answer to the query", - }, - }, - }, - }, - (inputs) => - testKit - .noop({ - template: - "Is this question about math? Answer YES or NO.\nQuestion: {{question}}\nAnswer: ", - question: inputs.question, - }) - .question.as("text") - .to( - testKit.noop({ - PALM_KEY: testKit.noop({ PALM_KEY: "dummy" }).PALM_KEY, - }) - ) - .to( - async (inputs) => { - const { text, math, search } = await inputs; - if ((text as string)?.startsWith("YES")) { - return { - result: math({ question: inputs.question }).result, - }; - } else { - return { - result: search({ text: inputs.question }).text, - }; - } - }, - { math, search } - ) - ); - - { - const { result } = await graph({ question: "YES it is" }); - t.is(result, "math result"); - } - - { - const { result } = await graph({ question: "NO it is" }); - t.is(result, "search result"); - } -}); diff --git a/packages/breadboard/tests/new/grammar/metadata.ts b/packages/breadboard/tests/new/grammar/metadata.ts deleted file mode 100644 index 3f217d60406..00000000000 --- a/packages/breadboard/tests/new/grammar/metadata.ts +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { board } from "../../../src/new/grammar/board.js"; - -import { testKit } from "../../helpers/_test-kit.js"; - -test("metadata in board constructor", async (t) => { - const graph = board( - { - input: { - type: "object", - required: ["foo"], - properties: { - foo: { - type: "string", - }, - }, - }, - output: { - type: "object", - required: ["foo"], - properties: { - foo: { - type: "string", - }, - }, - }, - url: "data:", - title: "test", - description: "test test", - version: "0.0.1", - }, - (inputs) => testKit.noop(inputs) - ); - - const serialized = await graph.serialize(); - - t.like(serialized, { - url: "data:", - title: "test", - description: "test test", - version: "0.0.1", - }); -}); - -test("metadata in serialize", async (t) => { - const graph = board((inputs) => testKit.noop(inputs)); - - const serialized = await graph.serialize({ - url: "data:", - title: "test", - description: "test test", - version: "0.0.1", - }); - - t.like(serialized, { - url: "data:", - title: "test", - description: "test test", - version: "0.0.1", - }); -}); - -test("metadata in serialize overrides metadata in constructor", async (t) => { - const graph = board( - { - input: { - type: "object", - required: ["foo"], - properties: { - foo: { - type: "string", - }, - }, - }, - output: { - type: "object", - required: ["foo"], - properties: { - foo: { - type: "string", - }, - }, - }, - title: "constructor", - description: "test test", - }, - (inputs) => testKit.noop(inputs) - ); - - const serialized = await graph.serialize({ - url: "data:", - title: "serialized", - }); - - t.like(serialized, { - url: "data:", - title: "serialized", - description: "test test", - }); -}); diff --git a/packages/breadboard/tests/new/grammar/serialize-and-run-with-old-runner.ts b/packages/breadboard/tests/new/grammar/serialize-and-run-with-old-runner.ts deleted file mode 100644 index 73807e5b41a..00000000000 --- a/packages/breadboard/tests/new/grammar/serialize-and-run-with-old-runner.ts +++ /dev/null @@ -1,249 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { board, code } from "../../../src/new/grammar/board.js"; -import { Serializeable } from "../../../src/new/runner/types.js"; -import { - InputValues, - OutputValues, - asRuntimeKit, - invokeGraph, -} from "../../../src/index.js"; - -import { TestKit, testKit } from "../../helpers/_test-kit.js"; - -async function serializeAndRunGraph( - graph: Serializeable, - inputs: InputValues -): Promise { - const board = await graph.serialize(); - return invokeGraph(board, inputs, { kits: [asRuntimeKit(TestKit)] }); -} - -test("simplest graph", async (t) => { - const graph = board((inputs) => { - return testKit.noop(inputs); - }); - const result = await serializeAndRunGraph(graph, { foo: "bar" }); - t.deepEqual(result, { foo: "bar" }); -}); - -test("simplest graph, spread", async (t) => { - const graph = board((inputs) => { - return testKit.noop({ ...inputs }); - }); - const result = await serializeAndRunGraph(graph, { foo: "bar" }); - t.deepEqual(result, { foo: "bar" }); -}); - -test("simplest graph, pick input", async (t) => { - const graph = board((inputs) => { - return testKit.noop({ foo: inputs.foo }); - }); - const result = await serializeAndRunGraph(graph, { foo: "bar" }); - t.deepEqual(result, { foo: "bar" }); -}); - -test("simplest graph, pick input and output", async (t) => { - const graph = board((inputs) => { - const { foo } = testKit.noop({ foo: inputs.foo }); - return { foo }; - }); - const result = await serializeAndRunGraph(graph, { foo: "bar" }); - t.like(result, { foo: "bar" }); -}); - -test("two nodes, spread", async (t) => { - const graph = board<{ [key: string]: string }>((inputs) => { - const reverser = testKit.reverser({ ...inputs }); - return testKit.noop({ ...reverser }); - }); - const result = await serializeAndRunGraph(graph, { foo: "bar" }); - t.deepEqual(result, { foo: "rab" }); -}); - -test("simple inline code", async (t) => { - const graph = board<{ a: number; b: number }, { result: number }>( - (inputs) => { - return code<{ a: number; b: number }, { result: number }>( - async (inputs) => { - const { a, b } = await inputs; - return { result: a + b }; - } - )({ a: inputs.a, b: inputs.b }); - } - ); - - const result = await serializeAndRunGraph(graph, { a: 1, b: 2 }); - t.deepEqual(result, { result: 3 }); -}); - -test("simple inline code, declare and cast types w/o contradiction", async (t) => { - const graph = board<{ a: number; b: number }, { result: number }>( - (inputs) => { - return { - result: code<{ a: number; b: number }, { result: number }>( - ({ a, b }) => { - return { result: a + b }; - } - )({ a: inputs.a.isNumber(), b: inputs.b.isNumber() }).result.isNumber(), - }; - } - ); - - const result = await serializeAndRunGraph(graph, { a: 1, b: 2 }); - t.like(result, { result: 3 }); -}); - -test("simple inline code, cast types and infer in TypeScript", async (t) => { - const graph = board((inputs) => { - return { - result: code(({ a, b }) => { - // TODO: Get rid of this extra cast, it shouldn't be necessary - return { result: (a as number) + (b as number) }; - })({ a: inputs.a.isNumber(), b: inputs.b.isNumber() }).result.isNumber(), - }; - }); - - const result = await serializeAndRunGraph(graph, { a: 1, b: 2 }); - t.like(result, { result: 3 }); -}); - -test("simple inline code, single parameter", async (t) => { - const graph = board<{ number: number }, { result: number }>((inputs) => { - return code<{ number: number }>((inputs) => { - return { result: -inputs.number }; - })(inputs); - }); - - const result = await serializeAndRunGraph(graph, { number: 3 }); - t.deepEqual(result, { result: -3 }); -}); - -test("simple inline code, single parameter, pick", async (t) => { - const graph = board<{ number: number }, { result: number }>(({ number }) => { - return code<{ number: number }>((inputs) => { - return { result: -inputs.number }; - })(number); - }); - - const result = await serializeAndRunGraph(graph, { number: 3 }); - t.deepEqual(result, { result: -3 }); -}); - -test("simple inline code, explicit input and output, single parameter", async (t) => { - const graph = board((_, base) => { - const inputs = base.input({ - schema: { - properties: { foo: { type: "string" } }, - required: ["foo"], - }, - }); - const neg = code(({ foo }) => { - return { result: `${foo}!!` }; - })(inputs); - const outputs = base.output({}); - neg.result.to(outputs); - }); - - const result = await serializeAndRunGraph(graph, { foo: "bar" }); - t.like(result, { result: "bar!!" }); -}); - -test("simple inline code, explicit input and output, single parameter, no schema", async (t) => { - const graph = board((_, base) => { - const inputs = base.input(); - const neg = code(({ foo }) => { - return { result: `${foo}!!` }; - })(inputs); - const outputs = base.output(); - neg.result.to(outputs); - }); - - const result = await serializeAndRunGraph(graph, { foo: "bar" }); - t.like(result, { result: "bar!!" }); -}); - -test("simple inline code, explicit input and output, single parameter, pick", async (t) => { - const graph = board((_, base) => { - const inputs = base.input({ - schema: { - properties: { foo: { type: "string" } }, - required: ["foo"], - }, - }); - const neg = code(({ foo }) => { - return { result: `${foo}!!` }; - })(inputs.foo); - const outputs = base.output({}); - neg.result.to(outputs); - }); - - const result = await serializeAndRunGraph(graph, { foo: "bar" }); - t.like(result, { result: "bar!!" }); -}); - -test("code board called from another board", async (t) => { - const add = code<{ a: number; b: number }, { result: number }>((inputs) => { - const { a, b } = inputs; - return { result: a + b }; - }); - - const graph = board<{ a: number; b: number }, { result: number }>( - (inputs) => { - return add({ a: inputs.a, b: inputs.b }); - } - ); - - const result = await serializeAndRunGraph(graph, { a: 1, b: 2 }); - t.deepEqual(result, { result: 3 }); -}); - -test("nested inline action, with schema", async (t) => { - const graph = board<{ a: number; b: number }>( - { - input: { - type: "object", - required: ["a", "b"], - properties: { - a: { - type: "string", - description: "A: One Number", - }, - b: { - type: "number", - description: "B: Another number", - }, - }, - }, - output: { - type: "object", - required: ["result"], - properties: { - result: { - type: "number", - title: "Sum", - description: "The sum of two numbers", - }, - }, - additionalProperties: false, - }, - }, - (inputs) => { - return code<{ a: number; b: number }, { result: number }>( - async (inputs) => { - const { a, b } = await inputs; - return { result: a + b }; - } - )({ a: inputs.a, b: inputs.b }); - } - ); - - const result = await serializeAndRunGraph(graph, { a: 1, b: 2 }); - t.deepEqual(result, { result: 3 }); -}); diff --git a/packages/breadboard/tests/new/runner/abort-early-in-invokeOnce.ts b/packages/breadboard/tests/new/runner/abort-early-in-invokeOnce.ts deleted file mode 100644 index d67c619ce46..00000000000 --- a/packages/breadboard/tests/new/runner/abort-early-in-invokeOnce.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { InputValues } from "../../../src/new/runner/types.js"; -import { Scope } from "../../../src/new/runner/scope.js"; -import { BaseNode } from "../../../src/new/runner/node.js"; - -test("abort once the first output is called", async (t) => { - const scope = new Scope(); - - const input = new BaseNode("input", scope); - const noop = new BaseNode("noop", scope); - const output = new BaseNode("output", scope); - const noop2 = new BaseNode("noop", scope); - noop.addIncomingEdge(input, "foo", "foo"); - output.addIncomingEdge(noop, "foo", "bar"); - noop2.addIncomingEdge(output, "", ""); - - scope.pin(output); - - let noopCalls = 0; - - const handlers = { - noop: (inputs: InputValues) => { - noopCalls++; - return { ...inputs }; - }, - }; - - scope.addHandlers(handlers); - - const result = await scope.invokeOneRound({ foo: "success" }); - - t.like(result, { bar: "success" }); - t.like(result, { $state: { queue: [noop2] } }); - t.is(noopCalls, 1); -}); diff --git a/packages/breadboard/tests/new/runner/default-schemas.ts b/packages/breadboard/tests/new/runner/default-schemas.ts deleted file mode 100644 index 1850bad1999..00000000000 --- a/packages/breadboard/tests/new/runner/default-schemas.ts +++ /dev/null @@ -1,137 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { board } from "../../../src/new/grammar/board.js"; - -import { testKit } from "../../helpers/_test-kit.js"; - -test("schema derived from reverser (has describe)", async (t) => { - const graph = board<{ foo: string }>(({ foo }) => ({ - bar: testKit.reverser({ foo }).foo, - })); - - const serialized = await graph.serialize(); - - const inputSchema = serialized.nodes.find((node) => node.type === "input") - ?.configuration?.schema; - const outputSchema = serialized.nodes.find((node) => node.type === "output") - ?.configuration?.schema; - - t.deepEqual(inputSchema, { - type: "object", - properties: { - foo: { type: "string", title: "foo", description: "Reverse: foo" }, - }, - required: ["foo"], - }); - - // Note "foo" as title, as this is determined by the reverse node. - t.deepEqual(outputSchema, { - type: "object", - properties: { - bar: { type: "string", title: "foo", description: "Reversed: foo" }, - }, - }); -}); - -test("schema derived from noop (no describe)", async (t) => { - const graph = board(({ foo }) => ({ - bar: testKit.noop({ foo }).foo, - })); - - const serialized = await graph.serialize(); - - const inputSchema = serialized.nodes.find((node) => node.type === "input") - ?.configuration?.schema; - const outputSchema = serialized.nodes.find((node) => node.type === "output") - ?.configuration?.schema; - - t.deepEqual(inputSchema, { - type: "object", - properties: { - foo: { type: "string", title: "foo" }, - }, - required: ["foo"], - }); - - t.deepEqual(outputSchema, { - type: "object", - properties: { - bar: { type: "string", title: "bar" }, - }, - }); -}); - -test("schema derived from noop, with type casts", async (t) => { - const graph = board(({ foo }) => ({ - bar: testKit - .noop({ - foo: foo.isNumber().title("The foo").description("A foo-lish number"), - }) - .foo.isNumber() - .description("A bar-ish number"), - })); - - const serialized = await graph.serialize(); - - const inputSchema = serialized.nodes.find((node) => node.type === "input") - ?.configuration?.schema; - const outputSchema = serialized.nodes.find((node) => node.type === "output") - ?.configuration?.schema; - - t.deepEqual(inputSchema, { - type: "object", - properties: { - foo: { - type: "number", - title: "The foo", - description: "A foo-lish number", - }, - }, - required: ["foo"], - }); - - t.deepEqual(outputSchema, { - type: "object", - properties: { - bar: { type: "number", title: "bar", description: "A bar-ish number" }, - }, - }); -}); - -test("schema derived from reverser, with type annotations", async (t) => { - const graph = board<{ foo: string }>(({ foo }) => ({ - bar: testKit - .reverser({ foo: foo.title("A foo") }) - .foo.description("Reversed bar"), - })); - - const serialized = await graph.serialize(); - - const inputSchema = serialized.nodes.find((node) => node.type === "input") - ?.configuration?.schema; - const outputSchema = serialized.nodes.find((node) => node.type === "output") - ?.configuration?.schema; - - t.deepEqual(inputSchema, { - type: "object", - properties: { - foo: { type: "string", title: "A foo", description: "Reverse: A foo" }, - }, - required: ["foo"], - }); - - // Note "A foo" as title, as this is determined by the reverse node, - // while description is overriden. - t.deepEqual(outputSchema, { - type: "object", - properties: { - bar: { type: "string", title: "A foo", description: "Reversed bar" }, - }, - }); -}); diff --git a/packages/breadboard/tests/new/runner/no-infinite-runs.ts b/packages/breadboard/tests/new/runner/no-infinite-runs.ts deleted file mode 100644 index eb593225b7f..00000000000 --- a/packages/breadboard/tests/new/runner/no-infinite-runs.ts +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { board } from "../../../src/new/grammar/board.js"; - -import { testKit } from "../../helpers/_test-kit.js"; - -test("broken graph should return an error", async (t) => { - const brokenGraph = board<{ foo: string }>(({ foo }) => ({ - bar: testKit.reverser({ foo }).bar, // Note: should be .foo - })); - - let result; - - try { - result = await brokenGraph({ foo: "bar" }); - } catch (e) { - t.is( - (e as Error).message, - "Output node never reached. Last node was reverser-3.\n\n" + - "These nodes had inputs missing:\n" + - " output-2: bar" - ); - } - t.deepEqual(result, { - $error: { - type: "error", - error: new Error( - "Output node never reached. Last node was reverser-3.\n\n" + - "These nodes had inputs missing:\n" + - " output-2: bar" - ), - }, - }); -}); diff --git a/packages/breadboard/tests/new/runner/pinning-scopes.ts b/packages/breadboard/tests/new/runner/pinning-scopes.ts deleted file mode 100644 index b767bea7528..00000000000 --- a/packages/breadboard/tests/new/runner/pinning-scopes.ts +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { InputValues } from "../../../src/new/runner/types.js"; -import { Scope } from "../../../src/new/runner/scope.js"; -import { BaseNode } from "../../../src/new/runner/node.js"; - -// Builds a test graph just using the primitives. -// Note that these nodes would be garbage collected if they weren't pinned. -function buildTestGraph(scope: Scope) { - const input = new BaseNode("input", scope); - const noop = new BaseNode("noop", scope); - const output = new BaseNode("output", scope); - noop.addIncomingEdge(input, "foo", "foo"); - output.addIncomingEdge(noop, "foo", "bar"); - - scope.pin(output); -} - -test("pin node and serialize scope", async (t) => { - const scope = new Scope(); - - buildTestGraph(scope); - - const serialized = await scope.serialize(); - - t.like(serialized, { - nodes: [ - { id: "output-3", type: "output" }, - { id: "noop-2", type: "noop" }, - { id: "input-1", type: "input" }, - ], - edges: [ - { from: "noop-2", to: "output-3", out: "foo", in: "bar" }, - { from: "input-1", to: "noop-2", out: "foo", in: "foo" }, - ], - }); -}); - -test("pin node and invoke scope", async (t) => { - const scope = new Scope(); - - buildTestGraph(scope); - - const inputs = { foo: "success" } satisfies InputValues; - let outputs: InputValues = { bar: "should be overwritten" }; - - const handlers = { - input: () => inputs, - noop: (inputs: InputValues) => inputs, - output: (inputs: InputValues) => { - outputs = inputs; - return inputs; - }, - }; - - scope.addHandlers(handlers); - - await scope.invoke(); - - t.is(outputs.bar, "success"); -}); - -test("pin node and invokeOnce scope", async (t) => { - const scope = new Scope(); - - buildTestGraph(scope); - - const handlers = { - noop: (inputs: InputValues) => inputs, - }; - - scope.addHandlers(handlers); - - const result = await scope.invokeOneRound({ foo: "success" }); - - t.deepEqual(result, { bar: "success" }); -}); - -test("multiple connected pins result in only pinning once", async (t) => { - const scope = new Scope(); - - t.is(scope.getPinnedNodes().length, 0); - - const input = new BaseNode("input", scope); - const noop = new BaseNode("noop", scope); - const output = new BaseNode("output", scope); - noop.addIncomingEdge(input, "foo", "foo"); - output.addIncomingEdge(noop, "foo", "bar"); - - scope.pin(input); - t.is(scope.getPinnedNodes().length, 1); - - scope.pin(output); - t.is(scope.getPinnedNodes().length, 2); - - scope.compactPins(); - t.is(scope.getPinnedNodes().length, 1); - - const noop2 = new BaseNode("noop", scope); - scope.pin(noop2); - - t.is(scope.getPinnedNodes().length, 2); - - scope.compactPins(); - t.is(scope.getPinnedNodes().length, 2); -}); diff --git a/packages/breadboard/tests/new/runner/state.ts b/packages/breadboard/tests/new/runner/state.ts deleted file mode 100644 index 77d511bc4b3..00000000000 --- a/packages/breadboard/tests/new/runner/state.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { BaseNode } from "../../../src/new/runner/node.js"; -import { Scope } from "../../../src/new/runner/scope.js"; -import { State } from "../../../src/new/runner/state.js"; - -test("transfer data across wires", async (t) => { - const scope = new Scope(); - const node1 = new BaseNode("noop", scope); - const node2 = new BaseNode("noop", scope); - - node2.addIncomingEdge(node1, "foo", "foo"); - - const state = new State(); - - t.false(state.missingInputs(node1)); - t.like(state.missingInputs(node2), ["foo"]); - - state.distributeResults( - { from: node1, to: node2, out: "foo", in: "foo" }, - { foo: "bar" } - ); - - t.false(state.missingInputs(node2)); - - const inputs = state.shiftInputs(node2); - t.deepEqual(inputs, { foo: "bar" }); - - t.like(state.missingInputs(node2), ["foo"]); -}); - -test("build and empty queue", async (t) => { - const scope = new Scope(); - const node = new BaseNode("noop", scope); - - const state = new State(); - - state.distributeResults( - { from: node, to: node, out: "foo", in: "foo" }, - { foo: "1" } - ); - - state.distributeResults( - { from: node, to: node, out: "foo", in: "foo" }, - { foo: "2" } - ); - - t.deepEqual(state.shiftInputs(node), { foo: "1" }); - t.deepEqual(state.shiftInputs(node), { foo: "2" }); - t.deepEqual(state.shiftInputs(node), {}); -}); diff --git a/packages/breadboard/tests/node.ts b/packages/breadboard/tests/node.ts deleted file mode 100644 index be6ef6dd2ad..00000000000 --- a/packages/breadboard/tests/node.ts +++ /dev/null @@ -1,133 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { parseSpec, Node, hasValues } from "../src/node.js"; -import { Board } from "../src/board.js"; - -test("parseSpec: control-only", (t) => { - t.deepEqual(parseSpec(""), { ltr: true, edge: {} }); - t.deepEqual(parseSpec("->"), { ltr: true, edge: {} }); - t.deepEqual(parseSpec("<-"), { ltr: false, edge: {} }); -}); - -test("parseSpec: all-value", (t) => { - t.deepEqual(parseSpec("*"), { ltr: true, edge: { out: "*" } }); - t.deepEqual(parseSpec("*->"), { ltr: true, edge: { out: "*" } }); - t.deepEqual(parseSpec("->*"), { ltr: true, edge: { out: "*" } }); - t.deepEqual(parseSpec("<-*"), { ltr: false, edge: { out: "*" } }); - t.deepEqual(parseSpec("*<-"), { ltr: false, edge: { out: "*" } }); -}); - -test("parseSpec: simple", (t) => { - t.deepEqual(parseSpec("a"), { ltr: true, edge: { out: "a", in: "a" } }); - t.deepEqual(parseSpec("->a"), { ltr: true, edge: { out: "a", in: "a" } }); - t.deepEqual(parseSpec("a->"), { ltr: true, edge: { out: "a", in: "a" } }); - t.deepEqual(parseSpec("<-a"), { ltr: false, edge: { out: "a", in: "a" } }); - t.deepEqual(parseSpec("a<-"), { ltr: false, edge: { out: "a", in: "a" } }); -}); - -test("parseSpec: simple with optional", (t) => { - t.deepEqual(parseSpec("a?"), { - ltr: true, - edge: { out: "a", in: "a", optional: true }, - }); - t.deepEqual(parseSpec("->a?"), { - ltr: true, - edge: { out: "a", in: "a", optional: true }, - }); - t.deepEqual(parseSpec("a->?"), { - ltr: true, - edge: { out: "a", in: "a", optional: true }, - }); - t.deepEqual(parseSpec("<-a?"), { - ltr: false, - edge: { out: "a", in: "a", optional: true }, - }); - t.deepEqual(parseSpec("a<-?"), { - ltr: false, - edge: { out: "a", in: "a", optional: true }, - }); -}); - -test("parseSpec: simple with constant", (t) => { - t.deepEqual(parseSpec("a."), { - ltr: true, - edge: { out: "a", in: "a", constant: true }, - }); - t.deepEqual(parseSpec("->a."), { - ltr: true, - edge: { out: "a", in: "a", constant: true }, - }); - t.deepEqual(parseSpec("a->."), { - ltr: true, - edge: { out: "a", in: "a", constant: true }, - }); - t.deepEqual(parseSpec("<-a."), { - ltr: false, - edge: { out: "a", in: "a", constant: true }, - }); - t.deepEqual(parseSpec("a<-."), { - ltr: false, - edge: { out: "a", in: "a", constant: true }, - }); -}); - -test("parseSpec: simple with optional and constant (invalid spec)", (t) => { - t.throws(() => parseSpec("a?.")); - t.throws(() => parseSpec("a.?")); -}); - -test("parseSpec: both in and out specified", (t) => { - t.deepEqual(parseSpec("a->b"), { ltr: true, edge: { out: "a", in: "b" } }); - t.deepEqual(parseSpec("a<-b"), { ltr: false, edge: { out: "b", in: "a" } }); -}); - -test("parseSpec: both in and out specified with optional", (t) => { - t.deepEqual(parseSpec("a->b?"), { - ltr: true, - edge: { out: "a", in: "b", optional: true }, - }); - t.deepEqual(parseSpec("a<-b?"), { - ltr: false, - edge: { out: "b", in: "a", optional: true }, - }); -}); - -test("parseSpec: both in and out specified with constant", (t) => { - t.deepEqual(parseSpec("a->b."), { - ltr: true, - edge: { out: "a", in: "b", constant: true }, - }); - t.deepEqual(parseSpec("a<-b."), { - ltr: false, - edge: { out: "b", in: "a", constant: true }, - }); -}); - -test("convert nodes in config to wires", async (t) => { - const board = new Board(); - const input = board.input(); - new Node(board, undefined, "test", { foo: input, "bar<-baz": input, baz: 1 }); - t.deepEqual(board.nodes, [ - { id: "input-1", type: "input" }, - { id: "test-2", type: "test", configuration: { baz: 1 } }, - ]); - t.deepEqual(board.edges, [ - { constant: true, from: "input-1", to: "test-2", in: "foo", out: "foo" }, - { from: "input-1", to: "test-2", in: "bar", out: "baz" }, - ]); -}); - -test("hasValue correctly tests for an empty object", (t) => { - t.false(hasValues({})); - t.true(hasValues({ foo: false })); - t.true(hasValues({ foo: 0 })); - t.true(hasValues({ foo: "" })); - t.true(hasValues({ foo: undefined })); - t.true(hasValues({ foo: null })); -}); diff --git a/packages/breadboard/tests/node/http/chunk-repair.ts b/packages/breadboard/tests/node/http/chunk-repair.ts deleted file mode 100644 index b5c38f53419..00000000000 --- a/packages/breadboard/tests/node/http/chunk-repair.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { chunkRepairTransform } from "../../../src/remote/chunk-repair.js"; -import { deepStrictEqual } from "node:assert"; - -const repair = async (incoming: string[], repaired: string[]) => { - const log: string[] = []; - const incomingStream = new ReadableStream({ - start(controller) { - for (const chunk of incoming) { - controller.enqueue(chunk); - } - controller.close(); - }, - }); - await incomingStream.pipeThrough(chunkRepairTransform()).pipeTo( - new WritableStream({ - write(chunk) { - log.push(chunk); - }, - }) - ); - deepStrictEqual(log, repaired); -}; - -describe("Chunk Repair Transform", async () => { - test("nice chunks", async () => { - await repair(["foo\n\n", "bar\n\n"], ["foo\n\n", "bar\n\n"]); - }); - test("broken chunks", async () => { - await repair(["foo\n", "\nbar\n\n"], ["foo\n\n", "bar\n\n"]); - await repair(["foo\n\nba", "r\n\n"], ["foo\n\n", "bar\n\n"]); - await repair( - ["foo\n\nbar\n\nb", "az\n\n"], - ["foo\n\n", "bar\n\n", "baz\n\n"] - ); - await repair( - ["foo\n\nbar\n\nbaz", "\n\nqux\n\n"], - ["foo\n\n", "bar\n\n", "baz\n\n", "qux\n\n"] - ); - await repair( - ["foo\n\nbar\n\nbaz\n\n", "qux\n\n"], - ["foo\n\n", "bar\n\n", "baz\n\n", "qux\n\n"] - ); - }); -}); diff --git a/packages/breadboard/tests/node/inspector/graph.ts b/packages/breadboard/tests/node/inspector/graph.ts deleted file mode 100644 index d5d7e8076ec..00000000000 --- a/packages/breadboard/tests/node/inspector/graph.ts +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import promptTemplate from "../../bgl/prompt-template.bgl.json" with { type: "json" }; -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; -import { inspectableGraph } from "../../../src/inspector/graph.js"; -import { testKit } from "../test-kit.js"; -import { createLoader } from "../../../src/index.js"; -import { deepEqual } from "node:assert"; - -describe("InspectableGraph", async () => { - test("uses describe entry point", async () => { - const graph = promptTemplate as GraphDescriptor; - const loader = createLoader(); - const inspectable = inspectableGraph(graph, { - kits: [testKit], - loader, - }); - const expected = { - inputSchema: { - type: "object", - properties: { - template: { - description: - "The template string to substitute the parameters into", - format: "multiline", - title: "Template", - type: "string", - }, - }, - required: ["template"], - }, - outputSchema: { - type: "object", - properties: { - prompt: { - type: "string", - format: "multiline", - title: "Prompt", - description: "The prompt string with the parameters substituted", - }, - }, - }, - }; - const result = await inspectable.describe(); - deepEqual(result, expected); - }); - - test("passes inputs to describe", async () => { - const graph = promptTemplate as GraphDescriptor; - const loader = createLoader(); - const inspectable = inspectableGraph(graph, { - kits: [testKit], - loader, - }); - const expected = { - inputSchema: { - type: "object", - properties: { - template: { - description: - "The template string to substitute the parameters into", - format: "multiline", - title: "Template", - type: "string", - }, - "p-name": { - description: 'The value to substitute for the parameter "name"', - title: "name", - type: "string", - }, - }, - required: ["template", "p-name"], - }, - outputSchema: { - type: "object", - properties: { - prompt: { - type: "string", - format: "multiline", - title: "Prompt", - description: "The prompt string with the parameters substituted", - }, - }, - }, - }; - const result = await inspectable.describe({ template: "Hello, {{name}}!" }); - deepEqual(result, expected); - }); -}); diff --git a/packages/breadboard/tests/node/run/interruptible-run-graph.ts b/packages/breadboard/tests/node/run/interruptible-run-graph.ts deleted file mode 100644 index 907a67e9998..00000000000 --- a/packages/breadboard/tests/node/run/interruptible-run-graph.ts +++ /dev/null @@ -1,167 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { interruptibleScriptedRun } from "../scripted-run.js"; - -import invokeWithBubblingInput from "../../bgl/invoke-board-with-bubbling-input.bgl.json" with { type: "json" }; -import manyInputs from "../../bgl/many-inputs.bgl.json" with { type: "json" }; -import manyOutputs from "../../bgl/many-outputs.bgl.json" with { type: "json" }; -import multiLevelInvoke from "../../bgl/multi-level-invoke.bgl.json" with { type: "json" }; -import simple from "../../bgl/simple.bgl.json" with { type: "json" }; -import mapWithBubblingInputs from "../../bgl/map-with-bubbling-inputs.bgl.json" with { type: "json" }; - -describe("interruptibleRunGraph end-to-end", async () => { - test("simple graph", async () => { - await interruptibleScriptedRun(simple, [ - { expected: { type: "input" }, inputs: { text: "Hello" } }, - { expected: { type: "output", outputs: [{ text: "Hello" }] } }, - ]); - }); - - test("many inputs", async () => { - await interruptibleScriptedRun(manyInputs, [ - { expected: { type: "input" }, inputs: { text1: "foo" } }, - { expected: { type: "input" }, inputs: { text2: "bar" } }, - { - expected: { - type: "output", - outputs: [ - { - "text-one": "foo", - "text-two": "bar", - }, - ], - }, - }, - ]); - }); - - test("many outputs", async () => { - await interruptibleScriptedRun(manyOutputs, [ - { expected: { type: "input" }, inputs: { start: "foo" } }, - { - expected: { - type: "output", - outputs: [{ one: "foo" }, { two: "foo" }], - }, - }, - ]); - }); - - test("invoke board with a bubbling input", async () => { - await interruptibleScriptedRun(invokeWithBubblingInput, [ - { - expected: { - type: "input", - state: { - "": { node: "input" }, - }, - }, - inputs: { name: "Bob" }, - }, - { - expected: { - type: "input", - state: { - "": { node: "invoke-b5fe388d" }, - "2": { node: "input" }, - }, - }, - inputs: { location: "New York" }, - }, - { - expected: { - type: "output", - outputs: [ - { - greeting: 'Greeting is: "Hello, Bob from New York!"', - }, - ], - }, - }, - ]); - }); - - test("invoke board multiple levels of nesting and bubbling", async () => { - await interruptibleScriptedRun(multiLevelInvoke, [ - { - expected: { - type: "input", - state: { - "": { node: "invoke-d5aa6bf1" }, - "1": { node: "input" }, - }, - }, - inputs: { name: "Bob" }, - }, - { - expected: { - type: "input", - state: { - "": { node: "invoke-d5aa6bf1" }, - "1": { node: "invoke-b5fe388d" }, - "1-2": { node: "input" }, - }, - }, - inputs: { location: "New York" }, - }, - { - expected: { - type: "output", - outputs: [ - { - greeting: 'Greeting is: "Hello, Bob from New York!"', - }, - ], - }, - }, - ]); - }); - - test("map with bubbling inputs", async () => { - await interruptibleScriptedRun(mapWithBubblingInputs, [ - { - expected: { - type: "input", - state: { - "": { - node: "map-6088d0ca", - }, - "2-0": { - node: "input", - }, - }, - }, - inputs: { location: "Neptune" }, - }, - { - expected: { - type: "input", - state: { - "": { - node: "map-6088d0ca", - }, - "2-1": { - node: "input", - }, - }, - }, - inputs: { location: "Mercury" }, - }, - { - expected: { - type: "output", - outputs: [ - { - greetings: "Hello, Bob from Neptune!\nHello, Alice from Mercury!", - }, - ], - }, - }, - ]); - }); -}); diff --git a/packages/breadboard/tests/node/run/local-runner.ts b/packages/breadboard/tests/node/run/local-runner.ts deleted file mode 100644 index 15e14afa578..00000000000 --- a/packages/breadboard/tests/node/run/local-runner.ts +++ /dev/null @@ -1,297 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; -import { deepStrictEqual, ok } from "node:assert"; -import test, { describe } from "node:test"; -import { LocalRunner } from "../../../src/harness/local-runner.js"; -import { createLoader } from "../../../src/loader/index.js"; -import { OutputResponse } from "../../../src/types.js"; -import { testKit } from "../test-kit.js"; -import { - EventLogEntry, - eventNamesFromLog, - logEvents, - queryLog, -} from "./test-utils.js"; - -import askForSecret from "../../bgl/ask-for-secret.bgl.json" with { type: "json" }; -import multiLevelInvoke from "../../bgl/multi-level-invoke.bgl.json" with { type: "json" }; -import simple from "../../bgl/simple.bgl.json" with { type: "json" }; - -const BGL_DIR = new URL("../../../tests/bgl/test.bgl.json", import.meta.url) - .href; - -describe("LocalRunner", async () => { - test("simple graph with no diagnostics", async () => { - const events: EventLogEntry[] = []; - const runner = new LocalRunner({ - runner: simple as GraphDescriptor, - url: import.meta.url, - loader: createLoader(), - kits: [testKit], - }); - logEvents(runner, events); - { - const result = await runner.run(); - ok(result == false); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), ["start", "input", "pause"]); - } - { - const result = await runner.run({ text: "foo" }); - ok(result == true); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "start", - "input", - "pause", - "resume", - "output", - "end", - ]); - const output = queryLog(events, "output") as OutputResponse; - deepStrictEqual(output.outputs, { text: "foo" }); - } - }); - - test("simple graph with diagnostics", async () => { - const events: [name: string, data: unknown][] = []; - const runner = new LocalRunner({ - runner: simple as GraphDescriptor, - url: import.meta.url, - loader: createLoader(), - kits: [testKit], - diagnostics: true, - }); - logEvents(runner, events); - { - const result = await runner.run(); - ok(result == false); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "start", - "graphstart", - "edge", - "nodestart", - "input", - "pause", - ]); - } - { - const result = await runner.run({ text: "foo" }); - ok(result == true); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "start", - "graphstart", - "edge", - "nodestart", - "input", - "pause", - "resume", - "nodeend", - "edge", - "nodestart", - "output", - "nodeend", - "graphend", - "end", - ]); - const output = queryLog(events, "output") as OutputResponse; - deepStrictEqual(output.outputs, { text: "foo" }); - } - }); - - test("multi-level invoke graph with diagnostics", async () => { - const events: EventLogEntry[] = []; - const graph = multiLevelInvoke as GraphDescriptor; - graph.url = BGL_DIR; - const runner = new LocalRunner({ - runner: multiLevelInvoke as GraphDescriptor, - url: import.meta.url, - loader: createLoader(), - kits: [testKit], - diagnostics: true, - }); - logEvents(runner, events); - { - const result = await runner.run(); - ok(!result); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "start", - "graphstart", - "edge", - "nodestart", - "graphstart", - "edge", - "nodestart", - "input", - "pause", - ]); - } - { - events.length = 0; - const result = await runner.run({ name: "Bob" }); - ok(!result); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "resume", - "nodeend", - "edge", - "nodestart", - "graphstart", - "edge", - "nodestart", - "input", - "pause", - ]); - } - { - events.length = 0; - const result = await runner.run({ location: "Neptune" }); - ok(result); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "resume", - "nodeend", - "edge", - "nodestart", - "nodeend", - "edge", - "skip", - "edge", - "nodestart", - "nodeend", - "graphend", - "nodeend", - "edge", - "nodestart", - "nodeend", - "edge", - "nodestart", - "nodeend", - "graphend", - "nodeend", - "edge", - "nodestart", - "output", - "nodeend", - "graphend", - "end", - ]); - const output = queryLog(events, "output") as OutputResponse; - deepStrictEqual(output.outputs, { - greeting: 'Greeting is: "Hello, Bob from Neptune!"', - }); - } - }); - - test("local runner provides schema for pending inputs", async () => { - const runner = new LocalRunner({ - runner: simple as GraphDescriptor, - url: import.meta.url, - loader: createLoader(), - kits: [testKit], - }); - const result = await runner.run(); - ok(!result); - const schema = runner.inputSchema(); - deepStrictEqual(schema, { - type: "object", - properties: { - text: { type: "string", title: "Text", examples: [] }, - }, - required: [], - }); - }); - - test("local runner correctly handles secret inputs", async () => { - const events: EventLogEntry[] = []; - const runner = new LocalRunner({ - runner: askForSecret as GraphDescriptor, - url: import.meta.url, - loader: createLoader(), - kits: [testKit], - diagnostics: true, - interactiveSecrets: true, - }); - logEvents(runner, events); - { - const result = await runner.run(); - ok(!result); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "start", - "graphstart", - "edge", - "nodestart", - "secret", - "pause", - ]); - } - { - events.length = 0; - deepStrictEqual(runner.secretKeys(), ["SECRET"]); - const result = await runner.run({ SECRET: "foo" }); - ok(result); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "resume", - "nodeend", - "graphend", - "end", - ]); - } - }); - - test("correctly calls the observer", async () => { - const runner = new LocalRunner({ - runner: simple as GraphDescriptor, - url: import.meta.url, - loader: createLoader(), - kits: [testKit], - }); - let observed = false; - runner.addObserver({ - runs() { - throw new Error("Not implemented"); - }, - load() { - throw new Error("Not implemented"); - }, - async observe() { - observed = true; - }, - }); - const result = await runner.run(); - ok(observed); - ok(!result); - }); - - test("can handle observers that throw errors", async () => { - const runner = new LocalRunner({ - runner: simple as GraphDescriptor, - url: import.meta.url, - loader: createLoader(), - kits: [testKit], - }); - runner.addObserver({ - runs() { - throw new Error("Not implemented"); - }, - load() { - throw new Error("Not implemented"); - }, - observe() { - throw new Error("I'm an observer that throws an error"); - }, - }); - const result = await runner.run(); - ok(!result); - }); -}); diff --git a/packages/breadboard/tests/node/run/remote-runner.ts b/packages/breadboard/tests/node/run/remote-runner.ts deleted file mode 100644 index fba63ce06fb..00000000000 --- a/packages/breadboard/tests/node/run/remote-runner.ts +++ /dev/null @@ -1,238 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; - -import { deepStrictEqual, ok } from "node:assert"; -import { RemoteRunner } from "../../../src/harness/remote-runner.js"; -import { GraphDescriptor, OutputResponse } from "../../../src/index.js"; -import { - EventLogEntry, - eventNamesFromLog, - logEvents, - mockFetch, - queryLog, -} from "./test-utils.js"; - -import askForSecret from "../../bgl/ask-for-secret.bgl.json" with { type: "json" }; -import simple from "../../bgl/simple.bgl.json" with { type: "json" }; -import multiLevelInvoke from "../../bgl/multi-level-invoke.bgl.json" with { type: "json" }; - -const BGL_DIR = new URL("../../../tests/bgl/test.bgl.json", import.meta.url) - .href; - -describe("RemoteRunner", async () => { - test("simple graph with no diagnostics", async () => { - const events: EventLogEntry[] = []; - - const runner = new RemoteRunner( - { - remote: { - type: "http", - key: "my-key", - url: "https://example.com/run", - }, - url: import.meta.url, - }, - mockFetch(simple) - ); - logEvents(runner, events); - { - const result = await runner.run(); - ok(result == false); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), ["start", "input", "pause"]); - } - { - const result = await runner.run({ text: "foo" }); - ok(result == true); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "start", - "input", - "pause", - "resume", - "output", - "end", - ]); - const output = queryLog(events, "output") as OutputResponse; - deepStrictEqual(output.outputs, { text: "foo" }); - } - }); - - test("simple graph with diagnostics", async () => { - const events: [name: string, data: unknown][] = []; - const runner = new RemoteRunner( - { - remote: { - type: "http", - key: "my-key", - url: "https://example.com/run", - }, - url: import.meta.url, - diagnostics: true, - }, - mockFetch(simple) - ); - logEvents(runner, events); - { - const result = await runner.run(); - ok(result == false); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "start", - "graphstart", - "edge", - "nodestart", - "input", - "pause", - ]); - } - { - const result = await runner.run({ text: "foo" }); - ok(result == true); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "start", - "graphstart", - "edge", - "nodestart", - "input", - "pause", - "resume", - "nodeend", - "edge", - "nodestart", - "output", - "nodeend", - "graphend", - "end", - ]); - const output = queryLog(events, "output") as OutputResponse; - deepStrictEqual(output.outputs, { text: "foo" }); - } - }); - - test("multi-level invoke graph with diagnostics", async () => { - const events: EventLogEntry[] = []; - const graph = multiLevelInvoke as GraphDescriptor; - graph.url = BGL_DIR; - const runner = new RemoteRunner( - { - remote: { - type: "http", - key: "my-key", - url: "https://example.com/run", - }, - url: import.meta.url, - diagnostics: true, - }, - mockFetch(graph) - ); - logEvents(runner, events); - { - const result = await runner.run(); - ok(!result); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "start", - "graphstart", - "edge", - "nodestart", - "graphstart", - "edge", - "nodestart", - "input", - "pause", - ]); - } - { - events.length = 0; - const result = await runner.run({ name: "Bob" }); - ok(!result); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "resume", - "nodeend", - "edge", - "nodestart", - "graphstart", - "edge", - "nodestart", - "input", - "pause", - ]); - } - { - events.length = 0; - const result = await runner.run({ location: "Neptune" }); - ok(result); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "resume", - "nodeend", - "edge", - "nodestart", - "nodeend", - "edge", - "edge", - "nodestart", - "nodeend", - "graphend", - "nodeend", - "edge", - "nodestart", - "nodeend", - "edge", - "nodestart", - "nodeend", - "graphend", - "nodeend", - "edge", - "nodestart", - "output", - "nodeend", - "graphend", - "end", - ]); - const output = queryLog(events, "output") as OutputResponse; - deepStrictEqual(output.outputs, { - greeting: 'Greeting is: "Hello, Bob from Neptune!"', - }); - } - }); - - test("correctly handles secret inputs", async () => { - const events: EventLogEntry[] = []; - const runner = new RemoteRunner( - { - remote: { - type: "http", - key: "my-key", - url: "https://example.com/run", - }, - url: import.meta.url, - diagnostics: true, - }, - mockFetch(askForSecret as GraphDescriptor) - ); - logEvents(runner, events); - { - const result = await runner.run(); - ok(result); - ok(!runner.running()); - deepStrictEqual(eventNamesFromLog(events), [ - "start", - "graphstart", - "edge", - "nodestart", - "nodeend", - "graphend", - "end", - ]); - } - }); -}); diff --git a/packages/breadboard/tests/node/run/test-utils.ts b/packages/breadboard/tests/node/run/test-utils.ts deleted file mode 100644 index 62c29518190..00000000000 --- a/packages/breadboard/tests/node/run/test-utils.ts +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; -import { HarnessRunner } from "../../../src/harness/types.js"; -import { fail } from "assert"; -import { - RemoteMessage, - RemoteRunRequestBody, - ServerRunConfig, -} from "../../../src/remote/types.js"; -import { testKit } from "../test-kit.js"; -import { createDefaultDataStore, createLoader } from "../../../src/index.js"; -import { handleRunGraphRequest } from "../../../src/remote/run-graph-server.js"; - -export type EventLogEntry = [name: string, data: unknown]; - -export const eventNamesFromLog = (log: EventLogEntry[]) => - log.map(([name]) => name); - -export const queryLog = (log: EventLogEntry[], name: string) => - log.find(([n]) => n == name)?.[1]; - -export const logEvents = (runner: HarnessRunner, events: EventLogEntry[]) => { - const eventNames = [ - "start", - "pause", - "resume", - "input", - "output", - "secret", - "error", - "skip", - "edge", - "graphstart", - "graphend", - "nodestart", - "nodeend", - "end", - ]; - eventNames.forEach((name) => { - runner.addEventListener(name, (event) => { - const e = event as unknown as { data: unknown }; - events.push([name, e.data]); - }); - }); -}; - -export const mockFetch = (graph: GraphDescriptor) => { - const result: typeof globalThis.fetch = async (request, init) => { - const url = request as string; - const { method, body } = init || {}; - if (method !== "POST") { - fail("Only POST requests are supported by mockFetch."); - } - if (url !== "https://example.com/run") { - fail(`Only "https://example.com/run" is supported by mockFetch.`); - } - if (!body) { - fail("No body provided in request."); - } - const { - $key, - $next: next, - $diagnostics: diagnostics, - ...inputs - } = JSON.parse(body as string) as RemoteRunRequestBody; - - if ($key !== "my-key") { - fail(`Invalid key provided. Use "my-key".`); - } - - const pipe = new TransformStream({ - transform(message, controller) { - controller.enqueue(`data: ${JSON.stringify(message)}\n\n`); - }, - }); - - const config: ServerRunConfig = { - graph, - url: import.meta.url, - kits: [testKit], - writer: pipe.writable.getWriter(), - loader: createLoader(), - dataStore: createDefaultDataStore(), - stateStore: { - async load(next?: string) { - return next ? JSON.parse(next as string) : undefined; - }, - async save(state) { - return JSON.stringify(state); - }, - }, - }; - - handleRunGraphRequest({ inputs: inputs, next, diagnostics }, config); - - return new Response(pipe.readable.pipeThrough(new TextEncoderStream())); - }; - return result; -}; diff --git a/packages/breadboard/tests/node/scripted-run.ts b/packages/breadboard/tests/node/scripted-run.ts deleted file mode 100644 index 624171aab48..00000000000 --- a/packages/breadboard/tests/node/scripted-run.ts +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphDescriptor, - InputValues, - OutputValues, -} from "@google-labs/breadboard-schema/graph.js"; -import { deepStrictEqual, fail } from "assert"; -import { - createLoader, - createRunStateManager, - RunArguments, - runGraph, -} from "../../src/index.js"; -import { ReanimationState } from "../../src/run/types.js"; -import { loadRunnerState } from "../../src/serialization.js"; -import { testKit } from "./test-kit.js"; - -const BGL_DIR = new URL("../../../tests/bgl/test.bgl.json", import.meta.url) - .href; - -export type ExpectedRunState = { node: string }; - -export type ExpectedResult = { - type: string; - state?: Record; - outputs?: OutputValues[]; -}; - -export type RunScriptEntry = { - inputs?: InputValues; - expected: ExpectedResult; -}; - -export async function interruptibleScriptedRun( - g: unknown, - script: RunScriptEntry[] -) { - const graph = g as GraphDescriptor; - graph.url = BGL_DIR; - let resumeFrom: ReanimationState = {}; - let inputs: InputValues | undefined; - for (const [index, scriptEntry] of script.entries()) { - // TODO: Move inputs into the current scriptEntry, rather than the previous - // one. - const state = createRunStateManager(resumeFrom, inputs); - const args: RunArguments = { - kits: [testKit], - state, - loader: createLoader(), - }; - let outputCount = 0; - let interrupted = false; - for await (const result of runGraph(graph, args)) { - const { type } = result; - const expectedRunResult = scriptEntry; - deepStrictEqual( - type, - expectedRunResult.expected.type, - `Script entry ${index}: expected ${expectedRunResult.expected.type}, got ${type}` - ); - if (type === "output") { - const expected = expectedRunResult.expected.outputs?.[outputCount]; - if (expected) { - deepStrictEqual(result.outputs, expected); - } - outputCount++; - } else if (type === "input") { - interrupted = true; - break; - } - } - if (interrupted) { - const reanimationState = state.lifecycle().reanimationState(); - if (scriptEntry.expected.state) { - for (const [key, expectedState] of Object.entries( - scriptEntry.expected.state - )) { - const entry = reanimationState?.states?.[key]; - if (!entry) { - fail(`Script entry ${index}: expected state at path "${key}"`); - } - const state = entry?.state; - if (!state) { - fail(`Script entry ${index}: expected state at path "${key}"`); - } - const result = loadRunnerState(state).state; - deepStrictEqual(result.descriptor.id, expectedState.node); - } - } - inputs = scriptEntry.inputs; - resumeFrom = reanimationState; - } else { - if (index !== script.length - 1) { - fail(`Script entry ${index}: unexpected end of run at`); - } - } - } -} diff --git a/packages/breadboard/tests/node/test-kit.ts b/packages/breadboard/tests/node/test-kit.ts deleted file mode 100644 index 5bc4e025071..00000000000 --- a/packages/breadboard/tests/node/test-kit.ts +++ /dev/null @@ -1,177 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { getGraphDescriptor } from "../../src/capability.js"; -import { invokeGraph } from "../../src/run/invoke-graph.js"; -import { InputValues, Kit, OutputValues } from "../../src/types.js"; - -// A simplest possible re-implementation of some nodes to be used in tests -// in tests/bgl/*. - -export const testKit: Kit = { - url: import.meta.url, - handlers: { - invoke: { - invoke: async (inputs, context) => { - const { $board, ...args } = inputs; - if (!$board) { - throw new Error("No board provided for the `invoke` handler"); - } - const graph = await getGraphDescriptor($board, context); - if (!graph) { - throw new Error( - "Unable to get graph descriptor from the board in `invoke` handler" - ); - } - const base = context.board?.url && new URL(context.board?.url); - const invocationContext = base - ? { - ...context, - base, - } - : { ...context }; - - return invokeGraph(graph, args, invocationContext); - }, - }, - map: { - invoke: async (inputs, context) => { - const { board, list = [] } = inputs; - if (!board) { - throw new Error("No board provided for the `map` handler"); - } - const graph = await getGraphDescriptor(board, context); - if (!graph) { - throw new Error( - "Unable to get graph descriptor from the board in `map` handler" - ); - } - let listArray; - if (typeof list === "string") { - listArray = JSON.parse(list); - } else { - listArray = list; - } - if (!Array.isArray(listArray)) { - throw new Error( - "In `map` handler, `list` port value is not an array" - ); - } - const base = context.board?.url && new URL(context.board?.url); - if (context.state) { - const result: OutputValues[] = []; - for (const [index, item] of listArray.entries()) { - const newContext = { - ...context, - base: base || context?.base, - invocationPath: [...(context?.invocationPath || []), index], - }; - const outputs = await invokeGraph( - graph, - { item, index, list }, - newContext - ); - result.push(outputs); - } - return { list: result } as OutputValues; - } else { - const result = await Promise.all( - listArray.map(async (item, index) => { - const newContext = { - ...context, - base: base || context?.base, - invocationPath: [...(context?.invocationPath || []), index], - }; - const outputs = await invokeGraph( - graph, - { item, index, list }, - newContext - ); - return outputs; - }) - ); - return { list: result } as OutputValues; - } - }, - }, - promptTemplate: { - invoke: async (inputs) => { - const { template, ...parameters } = inputs; - return promptTemplateHandler(template as string, parameters); - }, - }, - runJavascript: { - invoke: async (inputs) => { - const { code, functionName = "run", raw, ...args } = inputs; - const vm = await import("node:vm"); - const codeToRun = `${code}\n${functionName}(${JSON.stringify(args)});`; - const context = vm.createContext({ console, structuredClone }); - const script = new vm.Script(codeToRun); - const result = await script.runInNewContext(context); - return raw - ? result - : { - result: - typeof result === "string" ? result : JSON.stringify(result), - }; - }, - }, - secrets: { - invoke: async (inputs) => { - const { keys } = inputs as { keys: string[] }; - return Object.fromEntries( - keys.map((key: string) => [key, "secret-value"]) - ); - }, - }, - }, -}; - -// Copied from template-kit/src/nodes/prompt-template.ts -// On 2024-07-29. - -export const stringify = (value: unknown): string => { - if (typeof value === "string") return value; - if (value === undefined) return "undefined"; - return JSON.stringify(value, null, 2); -}; - -export const substitute = (template: string, values: InputValues) => { - return Object.entries(values).reduce( - (acc, [key, value]) => acc.replace(`{{${key}}}`, stringify(value)), - template - ); -}; - -export const parametersFromTemplate = ( - template: string | undefined -): string[] => { - if (!template) return []; - const matches = template.matchAll(/{{(?[\w-]+)}}/g); - const parameters = Array.from(matches).map( - (match) => match.groups?.name || "" - ); - const unique = Array.from(new Set(parameters)); - return unique; -}; - -const promptTemplateHandler = ( - template: string, - inputs: { [K: string]: unknown } -) => { - const parameters = parametersFromTemplate(template); - if (!parameters.length) return { prompt: template, text: template }; - - const substitutes = parameters.reduce((acc, parameter) => { - if (inputs[parameter] === undefined) - throw new Error(`Input is missing parameter "${parameter}"`); - return { ...acc, [parameter]: inputs[parameter] }; - }, {}); - - const prompt = substitute(template, substitutes); - // log.info(`Prompt: ${prompt}`); - return { prompt, text: prompt }; -}; diff --git a/packages/breadboard/tests/node/utils/graph-url-like.ts b/packages/breadboard/tests/node/utils/graph-url-like.ts deleted file mode 100644 index 43dc2781933..00000000000 --- a/packages/breadboard/tests/node/utils/graph-url-like.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { ok } from "node:assert"; -import test, { describe } from "node:test"; -import { graphUrlLike } from "../../../src/utils/graph-url-like.js"; - -describe("graph url-like", () => { - test("Recognizes strings of distinct URL-like structure", () => { - ok(graphUrlLike("https://example.com")); - ok(graphUrlLike("file:///path/to/file")); - ok(graphUrlLike("data:text/plain,Hello%2C%20World")); - ok(graphUrlLike("#foo")); - }); - test("Rejects strings that are not URL-like", () => { - ok(!graphUrlLike("specialist")); - ok(!graphUrlLike("awesome-node-type")); - ok(!graphUrlLike("https://")); - ok(!graphUrlLike("foo#bar")); - }); -}); diff --git a/packages/breadboard/tests/node/utils/handler.ts b/packages/breadboard/tests/node/utils/handler.ts deleted file mode 100644 index 666ed3ec02d..00000000000 --- a/packages/breadboard/tests/node/utils/handler.ts +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { getGraphHandler } from "../../../src/handler.js"; -import { deepStrictEqual, ok } from "node:assert"; -import { GraphDescriptor } from "@google-labs/breadboard-schema/graph.js"; -import simple from "../../bgl/simple.bgl.json" with { type: "json" }; -import { NodeDescriberResult, NodeDescriberWires } from "../../../src/types.js"; - -describe("getGraphHandler", () => { - test("returns undefined for non-URL-like type", async () => { - const handler = await getGraphHandler("awesome-node-type", {}); - ok(handler === undefined); - }); - - test("returns handler for URL-like type", async () => { - const handler = await getGraphHandler("https://example.com/1", { - loader: { - async load(url: string) { - ok(url === "https://example.com/1"); - return { - nodes: {}, - edges: {}, - } as GraphDescriptor; - }, - }, - }); - ok(handler !== undefined); - ok("invoke" in handler); - }); - - test("returns handler that can be invoked for URL-like type", async () => { - const handler = await getGraphHandler("https://example.com/2", { - loader: { - async load(url: string) { - ok(url === "https://example.com/2"); - return simple as GraphDescriptor; - }, - }, - }); - ok(handler !== undefined); - ok("invoke" in handler); - const result = await handler.invoke({ text: "hello" }, {}); - ok(result !== undefined); - deepStrictEqual(result, { text: "hello" }); - }); - - test("returns handler with a describer for URL-like type", async () => { - const handler = await getGraphHandler("https://example.com/3", { - loader: { - async load(url: string) { - ok(url === "https://example.com/3"); - return simple as GraphDescriptor; - }, - }, - }); - ok(handler !== undefined); - ok("describe" in handler); - const description = await handler.describe?.( - {}, - {}, - {}, - { - kits: [], - outerGraph: simple, - wires: {} as NodeDescriberWires, - } - ); - ok(description !== undefined); - deepStrictEqual(description, { - inputSchema: { - additionalProperties: false, - properties: { - text: { type: "string", examples: [], title: "Text" }, - }, - required: [], - type: "object", - }, - outputSchema: { - additionalProperties: false, - properties: { - text: { type: "string", examples: [], title: "Text" }, - }, - required: [], - type: "object", - }, - } as NodeDescriberResult); - }); -}); diff --git a/packages/breadboard/tests/node/utils/hash.ts b/packages/breadboard/tests/node/utils/hash.ts deleted file mode 100644 index de16c3500c9..00000000000 --- a/packages/breadboard/tests/node/utils/hash.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { hash } from "../../../src/utils/hash.js"; -import { deepStrictEqual } from "node:assert"; - -describe("hash", () => { - test("hashes a string", () => { - deepStrictEqual(hash("hello"), 181380007); - }); - - test("hashes an object", () => { - deepStrictEqual(hash({ a: "hello" }), 186885731); - }); - - test("hashes an array", () => { - deepStrictEqual(hash(["hello"]), 1327990477); - }); - - test("hashes a nested object", () => { - deepStrictEqual(hash({ a: { b: "hello" } }), 357563268); - }); - - test("hashes a undefined", () => { - deepStrictEqual(hash(undefined), 3288676927); - }); -}); diff --git a/packages/breadboard/tests/remote/http.ts b/packages/breadboard/tests/remote/http.ts deleted file mode 100644 index 8b9668ee3fc..00000000000 --- a/packages/breadboard/tests/remote/http.ts +++ /dev/null @@ -1,386 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { - HTTPClientTransport, - HTTPServerTransport, - parseWithStreamsTransform, -} from "../../src/remote/http.js"; -import { RunServer } from "../../src/remote/run.js"; -import { AnyRunRequestMessage } from "../../src/remote/types.js"; -import { Board } from "../../src/board.js"; -import { TestKit } from "../helpers/_test-kit.js"; -import { MockHTTPConnection } from "../helpers/_test-transport.js"; -import { StreamCapability, isStreamCapability } from "../../src/stream.js"; -import { NodeValue } from "../../src/types.js"; - -test("parseWithStreamsTransform works as expected", async (t) => { - const transform = parseWithStreamsTransform(); - const reader = new ReadableStream({ - start(controller) { - controller.enqueue(JSON.stringify("foo")); - controller.enqueue(JSON.stringify("bar")); - controller.enqueue(JSON.stringify({ value: { $type: "Stream", id: 0 } })); - controller.enqueue( - JSON.stringify(["http-stream-chunk", { chunk: "baz" }]) - ); - controller.enqueue( - JSON.stringify(["http-stream-chunk", { chunk: "qux" }]) - ); - controller.enqueue(JSON.stringify(["http-stream-end", {}])); - controller.close(); - }, - }) - .pipeThrough(transform) - .getReader(); - const result = await reader.read(); - t.false(result.done); - t.deepEqual(result.value, "foo"); - const result2 = await reader.read(); - t.false(result2.done); - t.deepEqual(result2.value, "bar"); - const result3 = await reader.read(); - t.false(result3.done); - t.truthy(result3.value.value); - t.true(isStreamCapability(result3.value.value)); - const result4 = await reader.read(); - t.true(result4.done); - const dataReader = result3.value.value.stream.getReader(); - const dataResult = await dataReader.read(); - t.false(dataResult.done); - t.deepEqual(dataResult.value, "baz"); - const dataResult2 = await dataReader.read(); - t.false(dataResult2.done); - t.deepEqual(dataResult2.value, "qux"); - const dataResult3 = await dataReader.read(); - t.true(dataResult3.done); -}); - -test("HTTPServerTransport does the basics", async (t) => { - const request = { - body: ["run", {}], - }; - const response = { - header() { - return; - }, - write: (response: unknown) => { - t.deepEqual(response, 'data: ["input",{"node":{"type":"input"}}]\n\n'); - return true; - }, - end: () => { - t.pass(); - }, - }; - const transport = new HTTPServerTransport(request, response); - const stream = transport.createServerStream(); - const writer = stream.writableResponses.getWriter(); - const reader = stream.readableRequests.getReader(); - const requestValue = await reader.read(); - t.deepEqual(requestValue.value, ["run", {}]); - t.false(requestValue.done); - const doneValue = await reader.read(); - t.true(doneValue.done); - await writer.write(["input", { node: { type: "input" } }]); - await writer.close(); -}); - -test("RunServer can use HTTPServerTransport", async (t) => { - const board = new Board(); - const kit = board.addKit(TestKit); - board.input({ foo: "bar" }).wire("*", kit.noop().wire("*", board.output())); - - const request = { - body: ["run", {}] as AnyRunRequestMessage, - }; - const response = { - header() { - return; - }, - write: (response: unknown) => { - const data = JSON.parse((response as string).slice(6)); - t.like(data, ["input", { node: { type: "input" } }]); - return true; - }, - end: () => { - t.pass(); - }, - }; - const transport = new HTTPServerTransport(request, response); - const server = new RunServer(transport); - await server.serve(board); -}); - -test("MockHTTPConnection works as advertised", async (t) => { - const connection = new MockHTTPConnection(); - connection.onRequest(async (request, response) => { - t.like(request, { - body: ["run", {}], - }); - response.write(JSON.stringify(["input", { node: {} }])); - response.end(); - }); - const response = await connection.fetch("http://example.com", { - method: "POST", - body: JSON.stringify(["run", {}]), - }); - t.true(response.ok); - const reader = response.body - ?.pipeThrough(new TextDecoderStream()) - .getReader(); - t.assert(reader); - const result = await reader?.read(); - t.false(result?.done); - t.deepEqual(result?.value, '["input",{"node":{}}]'); -}); - -test("MockHTTPConnection end-to-end test", async (t) => { - const connection = new MockHTTPConnection(); - const clientTransport = new HTTPClientTransport("http://example.com", { - fetch: connection.fetch, - }); - connection.onRequest(async (request, response) => { - const serverTransport = new HTTPServerTransport(request, response); - const stream = serverTransport.createServerStream(); - const reader = stream.readableRequests.getReader(); - const data = await reader.read(); - t.false(data.done); - t.deepEqual(data.value, ["run", {}]); - const writer = stream.writableResponses.getWriter(); - writer.write(["input", { node: {} }]); - writer.close(); - }); - const stream = clientTransport.createClientStream(); - const writer = stream.writableRequests.getWriter(); - const reader = stream.readableResponses.getReader(); - writer.write(["run", {}]); - writer.close(); - const data = await reader.read(); - t.false(data.done); - t.deepEqual(data.value, ["input", { node: {} }]); - const done = await reader.read(); - t.true(done.done); -}); - -test("HTTPClientTransport does the basics", async (t) => { - const transport = new HTTPClientTransport("http://example.com", { - fetch: async (url, init) => { - t.is(url, "http://example.com"); - t.like(init, { - method: "POST", - body: JSON.stringify(["run", {}]), - }); - return { - ok: true, - get body() { - return new ReadableStream({ - start(controller) { - const data = ["input", { node: {} }]; - const chunk = new TextEncoder().encode( - `data: ${JSON.stringify(data)}\n\n` - ); - controller.enqueue(chunk); - controller.close(); - }, - }); - }, - } as unknown as globalThis.Response; - }, - }); - const stream = transport.createClientStream(); - const writer = stream.writableRequests.getWriter(); - const reader = stream.readableResponses.getReader(); - writer.write(["run", {}]); - writer.close(); - const response = await reader.read(); - t.false(response.done); - t.deepEqual(response.value, ["input", { node: {} }]); - const done = await reader.read(); - t.true(done.done); -}); - -test("HTTPClientTransport handles broken chunks", async (t) => { - const connection = new MockHTTPConnection({ breakChunks: true }); - const clientTransport = new HTTPClientTransport("http://example.com", { - fetch: connection.fetch, - }); - connection.onRequest(async (request, response) => { - const serverTransport = new HTTPServerTransport(request, response); - const stream = serverTransport.createServerStream(); - const reader = stream.readableRequests.getReader(); - const data = await reader.read(); - t.false(data.done); - t.deepEqual(data.value, ["run", {}]); - const writer = stream.writableResponses.getWriter(); - writer.write(["input", { node: {} }]); - writer.close(); - }); - const stream = clientTransport.createClientStream(); - const writer = stream.writableRequests.getWriter(); - const reader = stream.readableResponses.getReader(); - writer.write(["run", {}]); - writer.close(); - const data = await reader.read(); - t.false(data.done); - t.deepEqual(data.value, ["input", { node: {} }]); - const done = await reader.read(); - t.true(done.done); -}); - -test("HTTPClientTransport complains about multiple writes", async (t) => { - const transport = new HTTPClientTransport("http://example.com", { - fetch: async (url, init) => { - t.is(url, "http://example.com"); - t.like(init, { - method: "POST", - body: JSON.stringify(["run", {}]), - }); - return { - ok: true, - get body() { - return new ReadableStream({ - start(controller) { - const data = ["input", { node: {} }]; - const chunk = new TextEncoder().encode(JSON.stringify(data)); - controller.enqueue(chunk); - controller.close(); - }, - }); - }, - } as unknown as globalThis.Response; - }, - }); - const stream = transport.createClientStream(); - const writer = stream.writableRequests.getWriter(); - writer.write(["run", {}]); - await t.throwsAsync(() => writer.write(["run", {}]), { - message: "HTTPClientTransport supports only one write per stream instance.", - }); -}); - -test("HTTPServerTransport handles output with a single stream in it", async (t) => { - const results: unknown[] = []; - const request = { - body: ["run", {}], - }; - const response = { - header() { - return; - }, - write: (response: unknown) => { - results.push(response); - return true; - }, - end: () => { - t.pass(); - }, - }; - const transport = new HTTPServerTransport(request, response); - const stream = transport.createServerStream(); - const writer = stream.writableResponses.getWriter(); - const reader = stream.readableRequests.getReader(); - const dataStream = new StreamCapability( - new ReadableStream({ - start(controller) { - controller.enqueue("foo"); - controller.enqueue("bar"); - controller.close(); - }, - }) - ); - const requestValue = await reader.read(); - t.deepEqual(requestValue.value, ["run", {}]); - t.false(requestValue.done); - const doneValue = await reader.read(); - t.true(doneValue.done); - await writer.write([ - "output", - { node: { type: "output" }, outputs: { dataStream } }, - ]); - writer.close(); - t.deepEqual(results, [ - 'data: ["output",{"node":{"type":"output"},"outputs":{"dataStream":{"$type":"Stream","id":0}}}]\n\n', - 'data: ["http-stream-chunk",{"chunk":"foo"}]\n\n', - 'data: ["http-stream-chunk",{"chunk":"bar"}]\n\n', - 'data: ["http-stream-end",{}]\n\n', - ]); -}); - -test("HTTPClientTransport handles input with a single stream in it", async (t) => { - const makeChunk = (data: unknown) => { - return new TextEncoder().encode(`data: ${JSON.stringify(data)}\n\n`); - }; - const transport = new HTTPClientTransport("http://example.com", { - fetch: async (url, init) => { - t.is(url, "http://example.com"); - t.like(init, { - method: "POST", - body: JSON.stringify(["run", {}]), - }); - return { - ok: true, - get body() { - return new ReadableStream({ - start(controller) { - const data = [ - "output", - { - node: { type: "output" }, - outputs: { - dataStream: { $type: "Stream", id: 0 }, - }, - }, - ]; - controller.enqueue(makeChunk(data)); - controller.enqueue( - makeChunk(["http-stream-chunk", { chunk: "foo" }]) - ); - controller.enqueue( - makeChunk(["http-stream-chunk", { chunk: "bar" }]) - ); - controller.enqueue(makeChunk(["http-stream-end", {}])); - controller.close(); - }, - }); - }, - } as unknown as globalThis.Response; - }, - }); - const stream = transport.createClientStream(); - const writer = stream.writableRequests.getWriter(); - const reader = stream.readableResponses.getReader(); - writer.write(["run", {}]); - writer.close(); - const data = await reader.read(); - t.false(data.done); - t.like(data.value, [ - "output", - { - node: { type: "output" }, - }, - ]); - const value = data.value as [ - type: string, - data: { outputs: { dataStream: NodeValue } }, - ]; - const dataStream = value[1].outputs.dataStream; - t.true(isStreamCapability(dataStream)); - const done = await reader.read(); - t.true(done.done); - const dataReader = ( - dataStream as StreamCapability - ).stream.getReader(); - const dataResult = await dataReader.read(); - t.false(dataResult.done); - t.deepEqual(dataResult.value, "foo"); - const dataResult2 = await dataReader.read(); - t.false(dataResult2.done); - t.deepEqual(dataResult2.value, "bar"); - const dataResult3 = await dataReader.read(); - t.true(dataResult3.done); -}); diff --git a/packages/breadboard/tests/remote/load.ts b/packages/breadboard/tests/remote/load.ts deleted file mode 100644 index ee2cd79939a..00000000000 --- a/packages/breadboard/tests/remote/load.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { createMockWorkers } from "../helpers/_test-transport.js"; -import { InitClient, InitServer } from "../../src/remote/init.js"; -import { - PortDispatcher, - WorkerClientTransport, - WorkerServerTransport, -} from "../../src/remote/worker.js"; - -test("InitServer and InitClient work together", async (t) => { - const mockWorkers = createMockWorkers(); - const hostDispatcher = new PortDispatcher(mockWorkers.host); - const workerDispatcher = new PortDispatcher(mockWorkers.worker); - const client = new InitClient( - new WorkerClientTransport(workerDispatcher.send("test")) - ); - const server = new InitServer( - new WorkerServerTransport(hostDispatcher.receive("test")) - ); - - const url = "https://example.com"; - client.load(url); - - await server.serve(); - - t.is(url, url); -}); diff --git a/packages/breadboard/tests/remote/proxy.ts b/packages/breadboard/tests/remote/proxy.ts deleted file mode 100644 index 9ed55b024f7..00000000000 --- a/packages/breadboard/tests/remote/proxy.ts +++ /dev/null @@ -1,249 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { - MockHTTPConnection, - createMockWorkers, -} from "../helpers/_test-transport.js"; -import { ProxyClient, ProxyServer } from "../../src/remote/proxy.js"; -import { - HTTPClientTransport, - HTTPServerTransport, -} from "../../src/remote/http.js"; -import { AnyProxyRequestMessage } from "../../src/remote/types.js"; -import { Board } from "../../src/board.js"; -import { MirrorUniverseKit, TestKit } from "../helpers/_test-kit.js"; -import { StreamCapability } from "../../src/stream.js"; -import { - PortDispatcher, - WorkerClientTransport, - WorkerServerTransport, -} from "../../src/remote/worker.js"; -import { asRuntimeKit, invokeGraph } from "../../src/index.js"; - -test("ProxyServer can use HTTPServerTransport", async (t) => { - const kits = [asRuntimeKit(TestKit)]; - const request = { - body: [ - "proxy", - { node: { id: "id", type: "noop" }, inputs: { hello: "world" } }, - ] as AnyProxyRequestMessage, - }; - const response = { - header() { - return; - }, - write: (response: unknown) => { - const data = JSON.parse((response as string).slice(6)); - t.deepEqual(data, ["proxy", { outputs: { hello: "world" } }]); - return true; - }, - end: () => { - t.pass(); - }, - }; - const transport = new HTTPServerTransport(request, response); - const server = new ProxyServer(transport); - await server.serve({ kits, proxy: ["noop"] }); -}); - -test("End-to-end proxy works with HTTP transports", async (t) => { - const connection = new MockHTTPConnection(); - connection.onRequest(async (request, response) => { - const kits = [asRuntimeKit(TestKit)]; - const server = new ProxyServer(new HTTPServerTransport(request, response)); - await server.serve({ kits, proxy: ["reverser"] }); - }); - const client = new ProxyClient( - new HTTPClientTransport("http://example.com", { fetch: connection.fetch }) - ); - const result = await client.proxy( - { id: "id", type: "reverser" }, - { hello: "world" }, - {} - ); - t.deepEqual(result, { hello: "dlrow" }); -}); - -test("ProxyClient creates functional proxy kits", async (t) => { - const connection = new MockHTTPConnection(); - connection.onRequest(async (request, response) => { - const kits = [asRuntimeKit(MirrorUniverseKit)]; - const server = new ProxyServer(new HTTPServerTransport(request, response)); - await server.serve({ kits, proxy: ["reverser"] }); - }); - const client = new ProxyClient( - new HTTPClientTransport("http://example.com", { fetch: connection.fetch }) - ); - const board = new Board(); - const kit = board.addKit(TestKit); - board - .input({ hello: "world" }) - .wire("*", kit.reverser().wire("*", board.output())); - const kits = [client.createProxyKit(["reverser"]), kit]; - const outputs = await invokeGraph(board, { hello: "world" }, { kits }); - t.deepEqual(outputs, { hello: "dlorw" }); -}); - -test("ProxyServer can be configured to tunnel nodes", async (t) => { - { - const connection = new MockHTTPConnection(); - connection.onRequest(async (request, response) => { - const kits = [asRuntimeKit(TestKit)]; - const server = new ProxyServer( - new HTTPServerTransport(request, response) - ); - await server.serve({ - kits, - proxy: [{ node: "test", tunnel: { hello: "reverser" } }, "reverser"], - }); - }); - const client = new ProxyClient( - new HTTPClientTransport("http://example.com", { fetch: connection.fetch }) - ); - const board = new Board(); - const kit = board.addKit(TestKit); - board - .input({ hello: "world" }) - .wire( - "*", - kit.test().wire("*", kit.reverser().wire("*", board.output())) - ); - const kits = [client.createProxyKit(["test", "reverser"]), kit]; - const outputs = await invokeGraph(board, { hello: "world" }, { kits }); - t.deepEqual(outputs, { hello: "dlrow" }); - } - { - const connection = new MockHTTPConnection(); - connection.onRequest(async (request, response) => { - const kits = [asRuntimeKit(TestKit)]; - const server = new ProxyServer( - new HTTPServerTransport(request, response) - ); - await server.serve({ - kits, - proxy: [ - { - node: "test", - tunnel: { - hello: { - to: "reverser", - when: { - hello: "bye", - }, - }, - }, - }, - "reverser", - ], - }); - }); - const client = new ProxyClient( - new HTTPClientTransport("http://example.com", { fetch: connection.fetch }) - ); - const board = new Board(); - const kit = board.addKit(TestKit); - board - .input({ hello: "world" }) - .wire( - "*", - kit.test().wire("*", kit.reverser().wire("*", board.output())) - ); - const kits = [client.createProxyKit(["test", "reverser"]), kit]; - const outputs = await invokeGraph(board, { hello: "world" }, { kits }); - t.deepEqual(outputs, { hello: "DEKCOLB_EULAV" }); - } -}); - -test("ProxyServer and ProxyClient correctly handle streams", async (t) => { - { - const connection = new MockHTTPConnection(); - connection.onRequest(async (request, response) => { - const kits = [asRuntimeKit(TestKit)]; - const server = new ProxyServer( - new HTTPServerTransport(request, response) - ); - await server.serve({ kits, proxy: ["streamer"] }); - }); - const client = new ProxyClient( - new HTTPClientTransport("http://example.com", { fetch: connection.fetch }) - ); - const board = new Board(); - const kit = board.addKit(TestKit); - board - .input({ hello: "world" }) - .wire("*", kit.streamer().wire("*", board.output())); - const kits = [client.createProxyKit(["streamer"]), kit]; - const outputs = await invokeGraph(board, { hello: "world" }, { kits }); - t.like(outputs, { stream: { kind: "stream" } }); - const stream = (outputs.stream as StreamCapability).stream; - const reader = stream.getReader(); - const chunks: string[] = []; - for (;;) { - const { done, value } = await reader.read(); - if (done) break; - chunks.push(value); - } - t.deepEqual( - chunks.join(""), - "Breadboard is a project that helps you make AI boards. " - ); - } - { - const mockWorkers = createMockWorkers(); - const hostDispatcher = new PortDispatcher(mockWorkers.host); - const workerDispatcher = new PortDispatcher(mockWorkers.worker); - - const client = new ProxyClient( - new WorkerClientTransport(hostDispatcher.send("proxy")) - ); - const server = new ProxyServer( - new WorkerServerTransport(workerDispatcher.receive("proxy")) - ); - server.serve({ kits: [asRuntimeKit(TestKit)], proxy: ["streamer"] }); - const board = new Board(); - const kit = board.addKit(TestKit); - board - .input({ hello: "world" }) - .wire("*", kit.streamer().wire("*", board.output())); - const kits = [client.createProxyKit(["streamer"]), kit]; - const outputs = await invokeGraph(board, { hello: "world" }, { kits }); - t.like(outputs, { stream: { kind: "stream" } }); - const stream = (outputs.stream as StreamCapability).stream; - const reader = stream.getReader(); - const chunks: string[] = []; - for (;;) { - const { done, value } = await reader.read(); - if (done) break; - chunks.push(value); - } - t.deepEqual( - chunks.join(""), - "Breadboard is a project that helps you make AI boards. " - ); - } -}); - -test("ProxyClient can shut down ProxyServer", async (t) => { - let done: () => void; - const mockWorkers = createMockWorkers(); - const hostDispatcher = new PortDispatcher(mockWorkers.host); - const workerDispatcher = new PortDispatcher(mockWorkers.worker); - - const proxyClient = new ProxyClient( - new WorkerClientTransport(hostDispatcher.send("proxy")) - ); - const proxyServer = new ProxyServer( - new WorkerServerTransport(workerDispatcher.receive("proxy")) - ); - proxyServer.serve({ kits: [] }).then(() => done()); - proxyClient.shutdownServer(); - t.pass(); - return new Promise((resolve) => { - done = resolve; - }); -}); diff --git a/packages/breadboard/tests/remote/transport.ts b/packages/breadboard/tests/remote/transport.ts deleted file mode 100644 index 9f6bff22a5e..00000000000 --- a/packages/breadboard/tests/remote/transport.ts +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { AnyRunRequestMessage, RemoteMessage } from "../../src/remote/types.js"; -import { Board } from "../../src/board.js"; -import { TestKit } from "../helpers/_test-kit.js"; -import { createMockWorkers } from "../helpers/_test-transport.js"; -import { RunClient, RunServer } from "../../src/remote/run.js"; -import { - PortDispatcher, - WorkerClientTransport, - WorkerServerTransport, -} from "../../src/remote/worker.js"; - -test("Continuous streaming", async (t) => { - const board = new Board(); - const kit = board.addKit(TestKit); - board.input({ foo: "bar" }).wire("*", kit.noop().wire("*", board.output())); - - // Set up the transports. - const mockWorkers = createMockWorkers(); - - const hostDispatcher = new PortDispatcher(mockWorkers.host); - const workerDispatcher = new PortDispatcher(mockWorkers.worker); - - const clientTransport = new WorkerClientTransport< - AnyRunRequestMessage, - RemoteMessage - >(hostDispatcher.send("test")); - const server = new RunServer( - new WorkerServerTransport(workerDispatcher.receive("test")) - ); - - // Serve the board. - server.serve(board, false, { kits: [kit] }); - - // Hand-craft running the board - const { writableRequests: requests, readableResponses: responses } = - clientTransport.createClientStream(); - const writer = requests.getWriter(); - const reader = responses.getReader(); - - writer.write(["run", {}]); - const firsResult = await reader.read(); - t.assert(!firsResult.done); - t.like(firsResult.value, [ - "input", - { node: { type: "input" }, inputArguments: { foo: "bar" } }, - ]); - writer.write(["input", { inputs: { hello: "world" } }, undefined as never]); - // second result was "beforehandler" (now "nodestart"), but I removed it - // because of the refactoring to use diagnostics. - const thirdResult = await reader.read(); - t.assert(!thirdResult.done); - t.like(thirdResult.value, ["output", { outputs: { hello: "world" } }]); - const fourthResult = await reader.read(); - t.assert(!fourthResult.done); - t.like(fourthResult.value, ["end"]); - const fifthResult = await reader.read(); - t.assert(fifthResult.done); -}); - -test("runOnce client can run once (client starts first)", async (t) => { - const board = new Board(); - const kit = board.addKit(TestKit); - board.input({ foo: "bar" }).wire("*", kit.noop().wire("*", board.output())); - - const mockWorkers = createMockWorkers(); - const hostDispatcher = new PortDispatcher(mockWorkers.host); - const workerDispatcher = new PortDispatcher(mockWorkers.worker); - - const client = new RunClient( - new WorkerClientTransport(hostDispatcher.send("test")) - ); - const server = new RunServer( - new WorkerServerTransport(workerDispatcher.receive("test")) - ); - - server.serve(board, false, { kits: [kit] }); - const outputs = await client.runOnce({ hello: "world" }); - - t.deepEqual(outputs, { hello: "world" }); -}); - -test("runOnce client can run once (server starts first)", async (t) => { - const board = new Board(); - const kit = board.addKit(TestKit); - board.input({ foo: "bar" }).wire("*", kit.noop().wire("*", board.output())); - - const mockWorkers = createMockWorkers(); - const hostDispatcher = new PortDispatcher(mockWorkers.host); - const workerDispatcher = new PortDispatcher(mockWorkers.worker); - - const server = new RunServer( - new WorkerServerTransport(workerDispatcher.receive("test")) - ); - const client = new RunClient( - new WorkerClientTransport(hostDispatcher.send("test")) - ); - - server.serve(board, false, { kits: [kit] }); - const outputs = await client.runOnce({ hello: "world" }); - - t.deepEqual(outputs, { hello: "world" }); -}); diff --git a/packages/breadboard/tests/remote/tunnel.ts b/packages/breadboard/tests/remote/tunnel.ts deleted file mode 100644 index e6a157d2911..00000000000 --- a/packages/breadboard/tests/remote/tunnel.ts +++ /dev/null @@ -1,571 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { - NodeTunnel, - getTunnelValue, - readNodeSpec, - replaceInputs, - replaceOutputs, - readConfig, - createTunnelKit, - createDestinationMap, - replaceTunnelledInputs, - scanTunnelValue, - atob, - btoa, -} from "../../src/remote/tunnel.js"; -import { callHandler } from "../../src/handler.js"; -import { NodeHandlers } from "../../src/types.js"; - -test("atob and btoa polyfills work", (t) => { - t.is(atob("aGVsbG8gd29ybGQ="), "hello world"); - t.is(btoa("hello world"), "aGVsbG8gd29ybGQ="); - t.is(atob(btoa("hello world")), "hello world"); -}); - -test("readNodeSpec works as advertised", (t) => { - const output = readNodeSpec("secrets", { - foo: "bar", - bar: ["foo", "baz"], - baz: { to: "foo", when: { foo: "bar" } }, - qux: [ - { to: "foo", when: { foo: "bar" } }, - { to: "baz", when: { foo: "foo" } }, - ], - }); - t.deepEqual(output, { - foo: [new NodeTunnel("foo", "secrets", "bar")], - bar: [ - new NodeTunnel("bar", "secrets", "foo"), - new NodeTunnel("bar", "secrets", "baz"), - ], - baz: [new NodeTunnel("baz", "secrets", "foo", { foo: "bar" })], - qux: [ - new NodeTunnel("qux", "secrets", "foo", { foo: "bar" }), - new NodeTunnel("qux", "secrets", "baz", { foo: "foo" }), - ], - }); -}); - -test("readConfig works as advertised", (t) => { - const output = readConfig({ - kits: [], - proxy: [ - "fetch", - { - node: "secrets", - tunnel: { - PALM_KEY: ["palm-generateText", "palm-embedText"], - }, - }, - ], - }); - t.deepEqual(output, { - secrets: { - PALM_KEY: [ - new NodeTunnel("PALM_KEY", "secrets", "palm-generateText"), - new NodeTunnel("PALM_KEY", "secrets", "palm-embedText"), - ], - }, - }); -}); - -test("replaceOutputs works as advertised", (t) => { - const output = replaceOutputs( - { - foo: "value here", - bar: "baz", - }, - { - foo: [new NodeTunnel("foo", "secrets", "bar")], - }, - (name, value) => `${name}=${value}` - ); - t.deepEqual(output, { - foo: "foo=value here", - bar: "baz", - }); -}); - -test("replaceInputs works as advertised", async (t) => { - { - const result = await replaceInputs( - { - url: "https://example.com", - foo: "bar", - }, - [ - new NodeTunnel("unused", "unused", "unused", { - url: "https://example2.com", - }), - ], - async (value, allow) => (allow ? `REPLACE=${value}` : "BLOCKED") - ); - t.deepEqual(result, { - url: "BLOCKED", - foo: "BLOCKED", - }); - } - { - const result = await replaceInputs( - { - url: "https://example.com", - foo: "bar", - }, - [ - new NodeTunnel("unused", "unused", "unused", { - url: "https://example.com", - }), - ], - async (value, allow) => (allow ? `REPLACE=${value}` : "BLOCKED") - ); - t.deepEqual(result, { - url: "REPLACE=https://example.com", - foo: "REPLACE=bar", - }); - } - { - const result = await replaceInputs( - { - url: "https://example.com", - foo: "bar", - }, - [ - new NodeTunnel("unused", "unused", "unused", { - url: /example\.com/, - }), - ], - async (value, allow) => (allow ? `REPLACE=${value}` : "BLOCKED") - ); - t.deepEqual(result, { - url: "REPLACE=https://example.com", - foo: "REPLACE=bar", - }); - } - { - const result = await replaceInputs( - { - url: "https://example.com", - foo: "bar", - }, - [ - new NodeTunnel("unused", "unused", "unused", { - url: /example2\.com/, - }), - ], - async (value, allow) => (allow ? `REPLACE=${value}` : "BLOCKED") - ); - t.deepEqual(result, { - url: "BLOCKED", - foo: "BLOCKED", - }); - } -}); - -test("createTunnelKit creates a kit that tunnels outputs", async (t) => { - const handlers = { - secrets: async () => { - return { API_KEY: "" }; - }, - } satisfies NodeHandlers; - const kit = createTunnelKit( - { - secrets: { - API_KEY: [ - new NodeTunnel("API_KEY", "secrets", "someNodeThatUsesAPIKey"), - ], - }, - }, - handlers - ); - t.deepEqual(await callHandler(handlers.secrets, {}, {}), { - API_KEY: "", - }); - t.deepEqual(await callHandler(kit.handlers.secrets, {}, {}), { - API_KEY: getTunnelValue("secrets", "API_KEY", {}), - }); -}); - -test("createTunnelKit creates a kit that tunnels outputs to inputs", async (t) => { - const handlers = { - secrets: async (inputs) => { - t.deepEqual(inputs, { keys: ["API_KEY"] }); - return { API_KEY: "" }; - }, - fetch: async (inputs) => { - t.deepEqual(inputs, { url: "", method: "POST" }); - return { result: "fetch result" }; - }, - } satisfies NodeHandlers; - const kit = createTunnelKit( - { - secrets: { - API_KEY: [new NodeTunnel("API_KEY", "secrets", "fetch")], - }, - }, - handlers - ); - - t.deepEqual( - await callHandler( - kit.handlers.fetch, - { - url: getTunnelValue("secrets", "API_KEY", { keys: ["API_KEY"] }), - method: "POST", - }, - {} - ), - { - result: "fetch result", - } - ); -}); - -test("createTunnelKit correctly blocks tunnels", async (t) => { - { - const handlers = { - secrets: async (inputs) => { - t.deepEqual(inputs, { keys: ["API_KEY"] }); - return { API_KEY: "" }; - }, - fetch: async (inputs) => { - t.deepEqual(inputs, { url: "VALUE_BLOCKED", method: "POST" }); - return { result: "fetch result" }; - }, - } satisfies NodeHandlers; - const kit = createTunnelKit( - { - secrets: { - API_KEY: [ - new NodeTunnel("API_KEY", "secrets", "fetch", { - url: /example\.com/, - }), - ], - }, - }, - handlers - ); - - t.deepEqual( - await callHandler( - kit.handlers.fetch, - { - url: getTunnelValue("secrets", "API_KEY", { keys: ["API_KEY"] }), - method: "POST", - }, - {} - ), - { - result: "fetch result", - } - ); - } - { - const handlers = { - secrets: async (inputs) => { - t.deepEqual(inputs, { keys: ["API_KEY"] }); - return { API_KEY: "" }; - }, - fetch: async (inputs) => { - t.deepEqual(inputs, { - url: "https://example.com/key=", - method: "POST", - }); - return { result: "fetch result" }; - }, - } satisfies NodeHandlers; - const kit = createTunnelKit( - { - secrets: { - API_KEY: [ - new NodeTunnel("API_KEY", "secrets", "fetch", { - url: /example\.com/, - }), - ], - }, - }, - handlers - ); - - t.deepEqual( - await callHandler( - kit.handlers.fetch, - { - url: `https://example.com/key=${getTunnelValue("secrets", "API_KEY", { - keys: ["API_KEY"], - })}`, - method: "POST", - }, - {} - ), - { - result: "fetch result", - } - ); - } -}); - -test("createTunnelKit correctly tunnels multiple inputs", async (t) => { - { - const handlers = { - secrets: async () => { - return { - API_KEY: "", - ANOTHER_KEY: "", - }; - }, - fetch: async (inputs) => { - t.deepEqual(inputs, { - url: "https://example.com/key=&another=", - method: "POST", - }); - return { result: "fetch result" }; - }, - } satisfies NodeHandlers; - const kit = createTunnelKit( - { - secrets: { - API_KEY: [new NodeTunnel("API_KEY", "secrets", "fetch")], - ANOTHER_KEY: [new NodeTunnel("ANOTHER_KEY", "secrets", "fetch")], - }, - }, - handlers - ); - - t.deepEqual( - await callHandler( - kit.handlers.fetch, - { - url: `https://example.com/key=${getTunnelValue("secrets", "API_KEY", { - keys: ["API_KEY"], - })}&another=${getTunnelValue("secrets", "ANOTHER_KEY", { - keys: ["ANOTHER_KEY"], - })}`, - method: "POST", - }, - {} - ), - { - result: "fetch result", - } - ); - } -}); - -test("createDestinationMap works as advertised", (t) => { - { - const output = createDestinationMap({ - secrets: { - API_KEY: [ - new NodeTunnel("API_KEY", "secrets", "someNodeThatUsesAPIKey"), - ], - }, - }); - t.deepEqual(output, { - someNodeThatUsesAPIKey: [ - new NodeTunnel("API_KEY", "secrets", "someNodeThatUsesAPIKey"), - ], - }); - } - { - const output = createDestinationMap({ - secrets: { - API_KEY: [ - new NodeTunnel("API_KEY", "secrets", "someNodeThatUsesAPIKey"), - ], - ANOTHER_KEY: [ - new NodeTunnel("ANOTHER_KEY", "secrets", "someNodeThatUsesAPIKey"), - ], - }, - }); - t.deepEqual(output, { - someNodeThatUsesAPIKey: [ - new NodeTunnel("API_KEY", "secrets", "someNodeThatUsesAPIKey"), - new NodeTunnel("ANOTHER_KEY", "secrets", "someNodeThatUsesAPIKey"), - ], - }); - } -}); - -test("createDestinationMap can handle tunnel collisions", (t) => { - const output = createDestinationMap({ - secrets: { - API_KEY: [ - new NodeTunnel("API_KEY", "secrets", "fetch", { - url: /www.googleapis.com\/customsearch\/v1/, - }), - ], - GOOGLE_CSE_ID: [ - new NodeTunnel("GOOGLE_CSE_ID", "secrets", "fetch", { - url: /www.googleapis.com\/customsearch\/v1/, - }), - ], - }, - }); - t.deepEqual(output, { - fetch: [ - new NodeTunnel("API_KEY", "secrets", "fetch", { - url: /www.googleapis.com\/customsearch\/v1/, - }), - new NodeTunnel("GOOGLE_CSE_ID", "secrets", "fetch", { - url: /www.googleapis.com\/customsearch\/v1/, - }), - ], - }); -}); - -test("scanTunnelValue works as advertised", (t) => { - const tunnelValue = getTunnelValue("nodeType", "outputName", { - inputName: "inputValue", - }); - t.deepEqual(scanTunnelValue(`HELLO${tunnelValue}WORLD`), [ - { value: "HELLO" }, - { - nodeType: "nodeType", - outputName: "outputName", - inputs: '{"inputName":"inputValue"}', - }, - { value: "WORLD" }, - ]); - t.deepEqual(scanTunnelValue(`HELLO${tunnelValue}`), [ - { value: "HELLO" }, - { - nodeType: "nodeType", - outputName: "outputName", - inputs: '{"inputName":"inputValue"}', - }, - ]); - t.deepEqual(scanTunnelValue(`${tunnelValue}WORLD`), [ - { - nodeType: "nodeType", - outputName: "outputName", - inputs: '{"inputName":"inputValue"}', - }, - { value: "WORLD" }, - ]); - t.deepEqual(scanTunnelValue(tunnelValue), [ - { - nodeType: "nodeType", - outputName: "outputName", - inputs: '{"inputName":"inputValue"}', - }, - ]); - t.deepEqual(scanTunnelValue(""), []); - t.deepEqual(scanTunnelValue("HELLO WORLD"), [{ value: "HELLO WORLD" }]); -}); - -test("replaceTunnelledInputs correctly round-trips objects", async (t) => { - const output = await replaceTunnelledInputs( - { - url: "https://example.com", - foo: "bar", - }, - false, - async (_, inputs) => { - return inputs; - } - ); - t.deepEqual(output, { - url: "https://example.com", - foo: "bar", - }); -}); - -test("replaceTunnelledInputs correctly replaces values in string inputs", async (t) => { - { - const output = await replaceTunnelledInputs( - `HELLO ${getTunnelValue("secrets", "API_KEY", { - API_KEY: ["API_KEY"], - })} WORLD`, - true, - async (_, inputs) => { - t.deepEqual(inputs, { API_KEY: ["API_KEY"] }); - return inputs; - } - ); - t.deepEqual(output, `HELLO ["API_KEY"] WORLD`); - } - { - const output = await replaceTunnelledInputs( - `HELLO ${getTunnelValue("secrets", "API_KEY", { - API_KEY: ["API_KEY"], - })} WORLD`, - true, - async (_, inputs) => { - t.deepEqual(inputs, { API_KEY: ["API_KEY"] }); - return { - API_KEY: "", - }; - } - ); - t.deepEqual(output, `HELLO WORLD`); - } -}); - -test("replaceTunnelledInputs correctly replaces values in object inputs", async (t) => { - { - const output = await replaceTunnelledInputs( - { - value: `HELLO ${getTunnelValue("secrets", "API_KEY", { - API_KEY: ["API_KEY"], - })} WORLD`, - }, - true, - async (_, inputs) => { - t.deepEqual(inputs, { API_KEY: ["API_KEY"] }); - return { - API_KEY: "", - }; - } - ); - t.deepEqual(output, { value: `HELLO WORLD` }); - } - { - const output = await replaceTunnelledInputs( - [ - `HELLO ${getTunnelValue("secrets", "API_KEY", { - API_KEY: ["API_KEY"], - })} WORLD`, - ], - true, - async (_, inputs) => { - t.deepEqual(inputs, { API_KEY: ["API_KEY"] }); - return { - API_KEY: "", - }; - } - ); - t.deepEqual(output, [`HELLO WORLD`]); - } -}); - -test("replaceTunnelledInputs correctly replaces multiple values", async (t) => { - { - const output = await replaceTunnelledInputs( - { - value: `HELLO ${getTunnelValue("secrets", "API_KEY", { - API_KEY: ["API_KEY"], - })} WORLD`, - also: getTunnelValue("secrets", "ANOTHER_KEY", { - ANOTHER_KEY: ["ANOTHER_KEY"], - }), - }, - true, - async () => { - return { - API_KEY: "", - ANOTHER_KEY: "", - }; - } - ); - t.deepEqual(output, { - value: `HELLO WORLD`, - also: "", - }); - } -}); diff --git a/packages/breadboard/tests/remote/worker.ts b/packages/breadboard/tests/remote/worker.ts deleted file mode 100644 index 897f3d0e9e4..00000000000 --- a/packages/breadboard/tests/remote/worker.ts +++ /dev/null @@ -1,178 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { createMockWorkers } from "../helpers/_test-transport.js"; -import { MirrorUniverseKit, TestKit } from "../helpers/_test-kit.js"; -import { ProxyClient, ProxyServer } from "../../src/remote/proxy.js"; -import { - PortDispatcher, - WorkerClientTransport, - WorkerServerTransport, -} from "../../src/remote/worker.js"; -import { Board } from "../../src/board.js"; -import { asRuntimeKit, invokeGraph } from "../../src/index.js"; - -test("Worker transports can handle ProxyServer and ProxyClient", async (t) => { - const workers = createMockWorkers(); - const hostDispatcher = new PortDispatcher(workers.host); - const workerDispatcher = new PortDispatcher(workers.worker); - - const server = new ProxyServer( - new WorkerServerTransport(hostDispatcher.receive("test")) - ); - server.serve({ - kits: [asRuntimeKit(MirrorUniverseKit)], - proxy: ["reverser"], - }); - - const client = new ProxyClient( - new WorkerClientTransport(workerDispatcher.send("test")) - ); - const board = new Board(); - const kit = board.addKit(TestKit); - board - .input({ hello: "world" }) - .wire("*", kit.reverser().wire("*", board.output())); - const kits = [client.createProxyKit(["reverser"]), kit]; - const outputs = await invokeGraph(board, { hello: "world" }, { kits }); - t.deepEqual(outputs, { hello: "dlorw" }); -}); - -test("Worker transports can handle proxy tunnels", async (t) => { - { - const workers = createMockWorkers(); - const hostDispatcher = new PortDispatcher(workers.host); - const workerDispatcher = new PortDispatcher(workers.worker); - - const server = new ProxyServer( - new WorkerServerTransport(hostDispatcher.receive("test")) - ); - - server.serve({ - kits: [asRuntimeKit(TestKit)], - proxy: [ - { - node: "test", - tunnel: { - hello: "reverser", - }, - }, - "reverser", - ], - }); - const client = new ProxyClient( - new WorkerClientTransport(workerDispatcher.send("test")) - ); - const board = new Board(); - const kit = board.addKit(TestKit); - board - .input({ hello: "world" }) - .wire( - "*", - kit.test().wire("*", kit.reverser().wire("*", board.output())) - ); - const kits = [client.createProxyKit(["test", "reverser"]), kit]; - const outputs = await invokeGraph(board, { hello: "world" }, { kits }); - t.deepEqual(outputs, { hello: "dlrow" }); - } - { - const workers = createMockWorkers(); - const hostDispatcher = new PortDispatcher(workers.host); - const workerDispatcher = new PortDispatcher(workers.worker); - - const server = new ProxyServer( - new WorkerServerTransport(hostDispatcher.receive("test")) - ); - server.serve({ - kits: [asRuntimeKit(TestKit)], - proxy: [ - { - node: "test", - tunnel: { - hello: { - to: "reverser", - when: { - hello: "bye", - }, - }, - }, - }, - "reverser", - ], - }); - const client = new ProxyClient( - new WorkerClientTransport(workerDispatcher.send("test")) - ); - const board = new Board(); - const kit = board.addKit(TestKit); - board - .input({ hello: "world" }) - .wire( - "*", - kit.test().wire("*", kit.reverser().wire("*", board.output())) - ); - const kits = [client.createProxyKit(["test", "reverser"]), kit]; - const outputs = await invokeGraph(board, { hello: "world" }, { kits }); - t.deepEqual(outputs, { hello: "DEKCOLB_EULAV" }); - } -}); - -test("PortDispatcher works as expected", async (t) => { - { - const workers = createMockWorkers(); - const hostDispatcher = new PortDispatcher(workers.host); - const workerDispatcher = new PortDispatcher(workers.worker); - - const hostPort = hostDispatcher.send("test"); - const workerPort = workerDispatcher.receive("test"); - - const writer = workerPort.writable.getWriter(); - writer.write("hello"); - writer.write("world"); - writer.close(); - - const reader = hostPort.readable.getReader(); - t.is((await reader.read()).value, "hello"); - t.is((await reader.read()).value, "world"); - t.is((await reader.read()).done, true); - } - { - const workers = createMockWorkers(); - const hostDispatcher = new PortDispatcher(workers.host); - const workerDispatcher = new PortDispatcher(workers.worker); - - const workerPort = workerDispatcher.receive("test"); - const hostPort = hostDispatcher.send("test"); - - const writer = workerPort.writable.getWriter(); - writer.write("hello"); - writer.write("world"); - writer.close(); - - const reader = hostPort.readable.getReader(); - t.is((await reader.read()).value, "hello"); - t.is((await reader.read()).value, "world"); - t.is((await reader.read()).done, true); - } - { - const workers = createMockWorkers(); - const hostDispatcher = new PortDispatcher(workers.host); - const workerDispatcher = new PortDispatcher(workers.worker); - - const workerPort = workerDispatcher.receive("test"); - const writer = workerPort.writable.getWriter(); - writer.write("hello"); - writer.write("world"); - writer.close(); - - const hostPort = hostDispatcher.send("test"); - const reader = hostPort.readable.getReader(); - t.is((await reader.read()).value, "hello"); - t.is((await reader.read()).value, "world"); - t.is((await reader.read()).done, true); - } -}); diff --git a/packages/breadboard/tests/result.ts b/packages/breadboard/tests/result.ts deleted file mode 100644 index e64586174a9..00000000000 --- a/packages/breadboard/tests/result.ts +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { MachineResult } from "../src/traversal/result.js"; -import { MachineEdgeState } from "../src/traversal/state.js"; - -test("MachineResult#skip", (t) => { - { - const result = new MachineResult( - { id: "test", type: "test" }, - {}, - ["input"], - { from: "from", to: "to" }, - [], - [], - new MachineEdgeState() - ); - t.true(result.skip); - } - { - const result = new MachineResult( - { id: "test", type: "test" }, - {}, - [], - { from: "from", to: "to" }, - [], - [], - new MachineEdgeState() - ); - t.false(result.skip); - } -}); diff --git a/packages/breadboard/tests/run.ts b/packages/breadboard/tests/run.ts deleted file mode 100644 index 818bdec0521..00000000000 --- a/packages/breadboard/tests/run.ts +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { RunResult } from "../src/run.js"; -import { Board } from "../src/board.js"; -import { TestKit } from "./helpers/_test-kit.js"; -import { replacer, reviver } from "../src/serialization.js"; -import { runGraph } from "../src/index.js"; - -test("replacer correctly serializes Maps", async (t) => { - t.is(JSON.stringify({}, replacer), "{}"); - t.is(JSON.stringify("string", replacer), '"string"'); - t.is(JSON.stringify(42, replacer), "42"); - t.is( - JSON.stringify(new Map([["foo", "bar"]]), replacer), - '{"$type":"Map","value":[["foo","bar"]]}' - ); - t.is( - JSON.stringify(new Map([["foo", new Map([["bar", "baz"]])]]), replacer), - '{"$type":"Map","value":[["foo",{"$type":"Map","value":[["bar","baz"]]}]]}' - ); -}); - -test("reviver correctly deserializes maps", async (t) => { - t.deepEqual(JSON.parse("{}", reviver), {}); - t.deepEqual(JSON.parse('"string"', reviver), "string"); - t.deepEqual(JSON.parse("42", reviver), 42); - t.deepEqual( - JSON.parse('{"$type":"Map","value":[["foo","bar"]]}', reviver), - new Map([["foo", "bar"]]) - ); - t.deepEqual( - JSON.parse( - '{"$type":"Map","value":[["foo",{"$type":"Map","value":[["bar","baz"]]}]]}', - reviver - ), - new Map([["foo", new Map([["bar", "baz"]])]]) - ); -}); - -test("correctly saves and loads", async (t) => { - let runResult = ""; - const board = new Board(); - const kit = board.addKit(TestKit); - const input = board.input(); - input.wire("<-", kit.noop()); - input.wire("*->", kit.noop().wire("*->", board.output().wire("*->", input))); - { - for await (const stop of runGraph(board, { kits: [kit] })) { - t.is(stop.type, "input"); - runResult = stop.save(); - break; - } - } - { - for await (const stop of runGraph( - board, - { kits: [kit] }, - RunResult.load(runResult)?.state - )) { - t.is(stop.type, "output"); - runResult = stop.save(); - break; - } - } - { - for await (const stop of runGraph( - board, - { kits: [kit] }, - RunResult.load(runResult)?.state - )) { - t.is(stop.type, "input"); - runResult = stop.save(); - break; - } - } - t.regex(runResult, /"missingInputs":\[\],.*"opportunities":\[\]/); -}); - -test("correctly detects exit node", async (t) => { - const board = new Board(); - const kit = board.addKit(TestKit); - const input = board.input(); - input.wire("*->", kit.noop().wire("*->", board.output())); - - const generator = runGraph(board, { kits: [kit] }); - - { - const stop = await generator.next(); - t.is(stop.value.type, "input"); - t.false(stop.value.isAtExitNode()); - } - - { - const stop = await generator.next(); - t.is(stop.value.type, "output"); - t.true(stop.value.isAtExitNode()); - } -}); diff --git a/packages/breadboard/tests/schema.ts b/packages/breadboard/tests/schema.ts deleted file mode 100644 index 5cdb0c0b0fa..00000000000 --- a/packages/breadboard/tests/schema.ts +++ /dev/null @@ -1,165 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { SchemaBuilder, getSchemaType } from "../src/schema.js"; - -test("getSchemaType returns the correct type for a value", (t) => { - t.is(getSchemaType(null), "null"); - t.is(getSchemaType(undefined), "null"); - t.is(getSchemaType(true), "boolean"); - t.is(getSchemaType(false), "boolean"); - t.is(getSchemaType(1), "number"); - t.is(getSchemaType(1.5), "number"); - t.is(getSchemaType("foo"), "string"); - t.is(getSchemaType({}), "object"); - t.is(getSchemaType([]), "array"); -}); - -test("SchemaBuilder can construct an empty schema", (t) => { - const builder = new SchemaBuilder(); - const schema = builder.build(); - t.deepEqual(schema, { - type: "object", - properties: {}, - additionalProperties: false, - }); -}); - -test("SchemaBuilder can construct a schema from inputs", (t) => { - { - const builder = new SchemaBuilder().addInputs({}); - const schema = builder.build(); - t.deepEqual(schema, { - type: "object", - properties: {}, - additionalProperties: false, - }); - } - { - const schema = new SchemaBuilder().addInputs().build(); - t.deepEqual(schema, { - type: "object", - properties: {}, - additionalProperties: false, - }); - } - { - const builder = new SchemaBuilder(); - builder.addInputs({ - foo: 1, - bar: "baz", - qux: true, - quux: null, - corge: undefined, - grault: [], - garply: {}, - }); - const schema = builder.build(); - t.deepEqual(schema, { - type: "object", - properties: { - foo: { type: "number" }, - bar: { type: "string" }, - qux: { type: "boolean" }, - quux: { type: "null" }, - corge: { type: "null" }, - grault: { type: "array" }, - garply: { type: "object" }, - }, - additionalProperties: false, - }); - } -}); - -test("SchemaBuilder can set `additionalProperties`", (t) => { - { - const builder = new SchemaBuilder().setAdditionalProperties(); - const schema = builder.build(); - t.deepEqual(schema, { - type: "object", - properties: {}, - additionalProperties: false, - }); - } - { - const builder = new SchemaBuilder().setAdditionalProperties(true); - const schema = builder.build(); - t.deepEqual(schema, { - type: "object", - properties: {}, - }); - } - { - const builder = new SchemaBuilder().setAdditionalProperties(false); - const schema = builder.build(); - t.deepEqual(schema, { - type: "object", - properties: {}, - additionalProperties: false, - }); - } -}); - -test("SchemaBuilder can add a property", (t) => { - const builder = new SchemaBuilder().addProperty("foo", { type: "string" }); - const schema = builder.build(); - t.deepEqual(schema, { - type: "object", - properties: { - foo: { type: "string" }, - }, - additionalProperties: false, - }); -}); - -test("SchemaBuilder can add properties", (t) => { - const builder = new SchemaBuilder().addProperties({ - foo: { type: "string" }, - bar: { type: "number" }, - }); - const schema = builder.build(); - t.deepEqual(schema, { - type: "object", - properties: { - foo: { type: "string" }, - bar: { type: "number" }, - }, - additionalProperties: false, - }); -}); - -test("SchemaBuilder can add required properties in order", (t) => { - const schema = new SchemaBuilder() - .addRequired(["foo"]) - .addRequired("bar") - .addRequired([]) - .addRequired() - .addRequired("") - .build(); - t.deepEqual(schema, { - type: "object", - properties: {}, - required: ["bar", "foo"], - additionalProperties: false, - }); -}); - -test("SchemaBuilder adds only unique required properties", (t) => { - const schema = new SchemaBuilder() - .addRequired(["foo", "bar"]) - .addRequired("foo") - .addRequired(["bar", "baz"]) - .addRequired("baz") - .build(); - t.deepEqual(schema, { - type: "object", - properties: {}, - required: ["bar", "baz", "foo"], - additionalProperties: false, - }); -}); diff --git a/packages/breadboard/tests/state.ts b/packages/breadboard/tests/state.ts deleted file mode 100644 index fb00fc2e731..00000000000 --- a/packages/breadboard/tests/state.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { MachineEdgeState } from "../src/traversal/state.js"; - -test("MachineEdgeState correctly manages queues", (t) => { - const state = new MachineEdgeState(); - - // Initial run. - state.wireOutputs( - [ - { from: "a", to: "b", out: "foo", in: "foo" }, - { from: "a", to: "b", out: "bar", in: "baz" }, - { from: "a", to: "c", out: "bar", in: "bar", constant: true }, - { from: "a", to: "d", out: "*" }, - ], // opportunities - { - foo: 1, - bar: 2, - } // outputs - ); - - // Now let's queue up more data - state.wireOutputs( - [{ from: "a", to: "b", out: "foo", in: "foo" }], // opportunities - { - foo: 3, - } // outputs - ); - - // Verify that inputs are were wired correctly. - t.deepEqual(state.getAvailableInputs("a"), {}); - t.deepEqual(state.getAvailableInputs("b"), { foo: 1, baz: 2 }); - t.deepEqual(state.getAvailableInputs("c"), { bar: 2 }); - t.deepEqual(state.getAvailableInputs("d"), { foo: 1, bar: 2 }); - - // Verify that the queues are emptied correctly. - state.useInputs("b", { foo: 1, baz: 2 }); - t.deepEqual(state.getAvailableInputs("b"), { foo: 3 }); - - // Verify that constants remain. - state.useInputs("c", { bar: 2 }); - t.deepEqual(state.getAvailableInputs("c"), { bar: 2 }); - - // Verify that using only inputs leaves the other queues as is. - state.useInputs("d", { foo: 1 }); - t.deepEqual(state.getAvailableInputs("d"), { bar: 2 }); -}); diff --git a/packages/breadboard/tests/stream.ts b/packages/breadboard/tests/stream.ts deleted file mode 100644 index 889d6a0b37c..00000000000 --- a/packages/breadboard/tests/stream.ts +++ /dev/null @@ -1,394 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { - StreamCapability, - isStreamCapability, - parseWithStreams, - portFactoryToStreams, - portToStreams, - streamFromAsyncGen, - streamFromReader, - streamFromWriter, - streamsToAsyncIterable, - stringifyWithStreams, -} from "../src/stream.js"; - -test("stringifyWithStreams works as expected", async (t) => { - { - const stream = new ReadableStream(); - const value = { - a: 1, - b: new StreamCapability(stream), - }; - const result = stringifyWithStreams(value); - t.deepEqual(result, { - value: '{"a":1,"b":{"$type":"Stream","id":0}}', - streams: [stream], - }); - } - { - const stream0 = new ReadableStream(); - const stream1 = new ReadableStream(); - const value = { - a: 1, - b: new StreamCapability(stream0), - c: { - d: new StreamCapability(stream1), - }, - }; - const result = stringifyWithStreams(value); - t.deepEqual(result, { - value: - '{"a":1,"b":{"$type":"Stream","id":0},"c":{"d":{"$type":"Stream","id":1}}}', - streams: [stream0, stream1], - }); - } - { - const value = { a: 1, b: { c: 2 } }; - const result = stringifyWithStreams(value); - t.deepEqual(result, { - value: '{"a":1,"b":{"c":2}}', - streams: [], - }); - } -}); - -test("parseWithStreams works as expected", async (t) => { - { - const stream = new ReadableStream(); - const value = { - a: 1, - b: { - $type: "Stream", - id: 0, - }, - }; - const result = parseWithStreams(JSON.stringify(value), () => stream); - t.deepEqual(result, { - a: 1, - b: new StreamCapability(stream), - }); - } - { - const stream0 = new ReadableStream(); - const stream1 = new ReadableStream(); - const value = { - a: 1, - b: { - $type: "Stream", - id: 0, - }, - c: { - d: { - $type: "Stream", - id: 1, - }, - }, - }; - const result = parseWithStreams(JSON.stringify(value), (id) => { - if (id === 0) return stream0; - if (id === 1) return stream1; - t.fail("invalid id"); - return null as unknown as ReadableStream; - }); - t.deepEqual(result, { - a: 1, - b: new StreamCapability(stream0), - c: { - d: new StreamCapability(stream1), - }, - }); - } - { - const value = { a: 1, b: { c: 2 } }; - const result = parseWithStreams(JSON.stringify(value), () => { - t.fail("should not be called"); - return null as unknown as ReadableStream; - }); - t.deepEqual(result, value); - } -}); - -test("streamFromAsyncGen simple", async (t) => { - async function* gen() { - yield 1; - yield 2; - yield 3; - } - const stream = streamFromAsyncGen(gen()); - const reader = stream.getReader(); - const results = []; - for (;;) { - const { done, value } = await reader.read(); - if (done) break; - results.push(value); - } - t.deepEqual(results, [1, 2, 3]); -}); - -test("streamFromAsyncGen as async iterator", async (t) => { - async function* gen() { - yield 1; - yield 2; - yield 3; - } - const stream = streamFromAsyncGen(gen()); - const results = []; - for await (const value of stream) { - results.push(value); - } - t.deepEqual(results, [1, 2, 3]); -}); - -test("portToStreams works as expected", async (t) => { - const { port1, port2 } = new MessageChannel(); - const port1streams = portToStreams(port1); - const port2streams = portToStreams(port2); - - const clientReader = port1streams.readable.getReader(); - const clientWriter = port1streams.writable.getWriter(); - - const serverReader = port2streams.readable.getReader(); - const serverWriter = port2streams.writable.getWriter(); - - { - const results = []; - - await serverWriter.write(1); - await serverWriter.write(2); - await serverWriter.write(3); - await serverWriter.close(); - - for (;;) { - const { done, value } = await clientReader.read(); - if (done) break; - results.push(value); - } - t.deepEqual(results, [1, 2, 3]); - } - - { - const results = []; - - await clientWriter.write(1); - await clientWriter.write(2); - await clientWriter.write(3); - await clientWriter.close(); - - for (;;) { - const { done, value } = await serverReader.read(); - if (done) break; - results.push(value); - } - t.deepEqual(results, [1, 2, 3]); - } -}); - -test("portToStreams correctly transfers value streams", async (t) => { - const { port1, port2 } = new MessageChannel(); - const port1streams = portToStreams(port1); - const port2streams = portToStreams(port2); - - const clientReader = port1streams.readable.getReader(); - const serverWriter = port2streams.writable.getWriter(); - - { - const stream = new ReadableStream({ - async pull(controller) { - controller.enqueue(1); - controller.enqueue(2); - controller.enqueue(3); - controller.close(); - }, - }); - await serverWriter.write(new StreamCapability(stream)); - await serverWriter.close(); - } - - { - const results = []; - - const streamValue = await clientReader.read(); - t.false(streamValue.done); - const stream = streamValue.value; - t.true(isStreamCapability(stream)); - const reader = (stream as StreamCapability).stream.getReader(); - for (;;) { - const { done, value } = await reader.read(); - if (done) break; - results.push(value); - } - - t.deepEqual(results, [1, 2, 3]); - } -}); - -test("streamsToAsyncIterable works as expected", async (t) => { - const results: (number | string)[] = []; - const readable = new ReadableStream({ - async pull(controller) { - controller.enqueue(1); - controller.enqueue(2); - controller.enqueue(3); - controller.close(); - }, - }); - const writable = new WritableStream({ - async write(chunk) { - results.push(chunk); - }, - async close() { - t.pass(); - }, - }); - const iterable = streamsToAsyncIterable(writable, readable); - for await (const value of iterable) { - results.push(value.data); - await value.reply(`number: ${value.data}`); - } - t.deepEqual(results, [1, "number: 1", 2, "number: 2", 3, "number: 3"]); -}); - -test("streamsToAsyncIterable can be used to start communication", async (t) => { - const results: (number | string)[] = []; - const readable = new ReadableStream({ - async pull(controller) { - controller.enqueue(1); - controller.enqueue(2); - controller.enqueue(3); - controller.close(); - }, - }); - const writable = new WritableStream({ - async write(chunk) { - results.push(chunk); - }, - async close() { - t.pass(); - }, - }); - const iterable = streamsToAsyncIterable(writable, readable); - await iterable.start("start"); - for await (const value of iterable) { - results.push(value.data); - await value.reply(`number: ${value.data}`); - } - t.deepEqual(results, [ - "start", - 1, - "number: 1", - 2, - "number: 2", - 3, - "number: 3", - ]); -}); - -test("streamFromReader produces a regular stream", async (t) => { - const readable = new ReadableStream({ - async pull(controller) { - controller.enqueue(1); - controller.enqueue(2); - controller.enqueue(3); - controller.close(); - }, - }); - const mainReader = readable.getReader(); - { - const stream = streamFromReader(mainReader); - const subReader = stream.getReader(); - const value = await subReader.read(); - t.deepEqual(value, { done: false, value: 1 }); - } - { - const stream = streamFromReader(mainReader); - const subReader = stream.getReader(); - const value1 = await subReader.read(); - t.deepEqual(value1, { done: false, value: 2 }); - const value2 = await subReader.read(); - t.deepEqual(value2, { done: false, value: 3 }); - } - { - const stream = streamFromReader(mainReader); - const subReader = stream.getReader(); - const value = await subReader.read(); - t.deepEqual(value, { done: true, value: undefined }); - } -}); - -test("streamFromWriter produces a regular stream", async (t) => { - const results: number[] = []; - const writable = new WritableStream({ - async write(chunk) { - results.push(chunk); - }, - }); - const mainWriter = writable.getWriter(); - { - const stream = streamFromWriter(mainWriter); - const subWriter = stream.getWriter(); - await subWriter.write(1); - await subWriter.close(); - } - { - const stream = streamFromWriter(mainWriter); - const subWriter = stream.getWriter(); - await subWriter.write(2); - await subWriter.close(); - } - { - const stream = streamFromWriter(mainWriter); - const subWriter = stream.getWriter(); - await subWriter.close(); - } - t.deepEqual(results, [1, 2]); - t.is(writable.locked, true); -}); - -test("portFactoryToStreams works as expected", async (t) => { - const results: (number | string | undefined)[] = []; - let done: () => void; - const createPort2 = async () => { - const { port1, port2 } = new MessageChannel(); - const port1streams = portToStreams(port1); - const writer = port1streams.writable.getWriter(); - writer.write(1); - writer.write(2); - writer.write(3); - writer.close(); - const reader = port1streams.readable.getReader(); - reader.read().then((value) => { - results.push(value.value); - reader.read().then((value) => { - results.push(value.value); - reader.read().then((value) => { - results.push(value.value); - reader.read().then((value) => { - results.push(value.value); - t.deepEqual(results, ["a", 1, 2, 3, "b", "c", undefined]); - done(); - }); - }); - }); - }); - return port2; - }; - const port2streams = portFactoryToStreams(createPort2); - const reader = port2streams.readable.getReader(); - const writer = port2streams.writable.getWriter(); - await writer.write("a"); - results.push((await reader.read()).value); - await writer.write("b"); - results.push((await reader.read()).value); - await writer.write("c"); - results.push((await reader.read()).value); - writer.close(); - return new Promise((resolve) => { - done = resolve; - }); -}); diff --git a/packages/breadboard/tests/type-checks.ts b/packages/breadboard/tests/type-checks.ts deleted file mode 100644 index dc70c9bc7f3..00000000000 --- a/packages/breadboard/tests/type-checks.ts +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * This file is used to make assertions about the type system of Breadboard. - * - * Use a `@ts-expect-error ` comment to assert that an expression - * should result in an error. These assertions are checked by `npm run - * build:tsc`. - * - * Use a `$ExpectType ` comment above an expression to assert its type. - * Note that it needs to match the type signature exactly. These assertions are - * checked by `npm run lint` which is configured to use - * https://github.com/JoshuaKGoldberg/eslint-plugin-expect-type. - */ - -import { base, board } from "../src/index.js"; -import type { InputValues } from "../src/types.js"; - -// Automatic input node ports should be typed as `unknown` by default. -board(({ foo, bar }) => { - // $ExpectType AbstractValue & ((config?: BuilderNodeConfig | undefined) => NodeProxy) - foo; - - // $ExpectType AbstractValue & ((config?: BuilderNodeConfig | undefined) => NodeProxy) - bar; -}); - -// Automatic input node ports should be typed according to the board call's -// generic parameters. -board<{ foo: string; bar: number }>(({ foo, bar }) => { - // $ExpectType AbstractValue & ((config?: BuilderNodeConfig | undefined) => NodeProxy) - foo; - - // $ExpectType AbstractValue & ((config?: BuilderNodeConfig | undefined) => NodeProxy) - bar; -}); - -// Automatic input node port's isString(), isNumber() etc. methods should return -// a version of that port with a different type. -board(({ foo }) => { - // $ExpectType AbstractValue - foo.isString(); - - // $ExpectType AbstractValue - foo.isNumber(); -}); - -// @ts-expect-error Passing an automatic input port to an automatic output of a -// different type. -board<{ foo: string }, { foo: number }>(({ foo }) => { - return { foo }; -}); - -// @ts-expect-error Passing a weakly typed automatic input port to a strongly -// typed automatic output port. -board(({ foo }) => { - return { foo }; -}); - -// TODO(aomarks) This should fail but doesn't. -// // @ts-expect-error Passing a strongly typed automatic input port to a weakly -// // typed automatic output port. -// board<{ foo: number }>(({ foo }) => { -// return { foo }; -// }); - -// Directly created input nodes should be typed as `unknown` by default. -board(() => { - // $ExpectType NodeProxy - const inputs = base.input({ $id: "input-1" }); - - // $ExpectType AbstractValue & ((...args: unknown[]) => unknown) & ((...args: unknown[]) => unknown) - inputs.foo; - - // $ExpectType AbstractValue & ((...args: unknown[]) => unknown) & ((...args: unknown[]) => unknown) - inputs.bar; -}); - -// Directly created input node port's isString(), isNumber() etc. methods should -// return a version of that port with a different type. -board(() => { - // $ExpectType NodeProxy - const inputs = base.input({ $id: "input-1" }); - - // $ExpectType AbstractValue - inputs.foo.isString(); - - // $ExpectType AbstractValue - inputs.bar.isNumber(); -}); diff --git a/packages/breadboard/tests/utils/async-gen.ts b/packages/breadboard/tests/utils/async-gen.ts deleted file mode 100644 index 2107d99c2de..00000000000 --- a/packages/breadboard/tests/utils/async-gen.ts +++ /dev/null @@ -1,123 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { asyncGen } from "../../src/utils/async-gen.js"; - -test("asyncGen basics work", async (t) => { - const results = []; - const yields = []; - - async function* foo() { - yield 1; - yield* asyncGen(async (next) => { - results.push(1.5); - await next(2); - results.push(2.5); - await next(3); - results.push(3.5); - }); - yield 4; - } - - for await (const val of foo()) { - results.push(val); - yields.push(val); - } - - t.deepEqual(results, [1, 1.5, 2, 2.5, 3, 3.5, 4]); - t.deepEqual(yields, [1, 2, 3, 4]); -}); - -test("asyncGen call to next is optional", async (t) => { - const results = []; - const yields = []; - - async function* foo() { - yield 1; - yield* asyncGen(async () => { - results.push(1.5); - }); - yield 2; - } - - for await (const val of foo()) { - results.push(val); - yields.push(val); - } - - t.deepEqual(results, [1, 1.5, 2]); - t.deepEqual(yields, [1, 2]); -}); - -test("asyncGen can handle exceptions", async (t) => { - const results = []; - const yields = []; - - async function* foo() { - yield 1; - yield* asyncGen(async (next) => { - results.push(1.5); - await next(2); - results.push(2.5); - throw new Error("test"); - }); - yield 3; - } - - try { - for await (const val of foo()) { - results.push(val); - yields.push(val); - } - } catch (e) { - t.is((e as Error).message, "test"); - } - - t.deepEqual(results, [1, 1.5, 2, 2.5]); - t.deepEqual(yields, [1, 2]); -}); - -test("asyncGen correctly waits for next", async (t) => { - async function* foo() { - yield* asyncGen<{ value: number }>(async (next) => { - const state = { value: 1 }; - await next(state); - t.is(state.value, 2); - state.value++; - await next(state); - t.is(state.value, 4); - }); - } - - for await (const val of foo()) { - val.value++; - } -}); - -test("asyncGen non-awaited next calls queue correctly", async (t) => { - const results = []; - async function* foo() { - yield* asyncGen(async (next) => { - results.push(0.5); - next(1); - results.push(1.5); - next(2); - results.push(2.5); - await next(3); - results.push(3.5); - next(4); - results.push(4.5); - }); - } - const yields = []; - for await (const val of foo()) { - yields.push(val); - results.push(val); - } - t.deepEqual(yields, [1, 2, 3, 4]); - t.deepEqual(results, [0.5, 1.5, 2.5, 1, 2, 3, 3.5, 4.5, 4]); -}); diff --git a/packages/breadboard/tsconfig.json b/packages/breadboard/tsconfig.json deleted file mode 100644 index f916280d732..00000000000 --- a/packages/breadboard/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "outDir": "./dist", - "resolveJsonModule": true, - "esModuleInterop": true - }, - "include": ["src/**/*", "tests/**/*", "tests/**/*.bgl.json"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/build-code/.eslintrc b/packages/build-code/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/build-code/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/build-code/CHANGELOG.md b/packages/build-code/CHANGELOG.md deleted file mode 100644 index 5cc843b01f9..00000000000 --- a/packages/build-code/CHANGELOG.md +++ /dev/null @@ -1,41 +0,0 @@ -# @breadboard-ai/build-code - -## 0.1.0 - -### Minor Changes - -- 2fa05f0: Initial release of @breadboard-ai/build-code - -### Patch Changes - -- 0985a47: Fix some issues with the build-code binary -- 0ef793f: Switch to typescript-json-schema because it can resolve more complex types -- Updated dependencies [49e2740] -- Updated dependencies [54c8197] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [2fa05f0] -- Updated dependencies [f61ccf3] -- Updated dependencies [f71bcfb] -- Updated dependencies [3188607] -- Updated dependencies [88298d5] -- Updated dependencies [b673bfa] -- Updated dependencies [8540b93] -- Updated dependencies [feeed7a] -- Updated dependencies [8330f0c] -- Updated dependencies [1423647] -- Updated dependencies [9783ba8] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [91fe8bb] -- Updated dependencies [100fc95] -- Updated dependencies [4423c35] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [5834c81] -- Updated dependencies [0ef793f] -- Updated dependencies [9c04caa] - - @breadboard-ai/build@0.10.0 - - @google-labs/core-kit@0.15.0 diff --git a/packages/build-code/README.md b/packages/build-code/README.md deleted file mode 100644 index e86e8ec0d04..00000000000 --- a/packages/build-code/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# build-code - -[![Published on npm](https://img.shields.io/npm/v/@breadboard-ai/build-code.svg?logo=npm)](https://www.npmjs.com/package/@breadboard-ai/build-code) - -Converts TypeScript functions to Breadboard `runJavascript` components. Code is -bundled and schema is automaticaly generated from TypeScript types. - -## Usage - -1. Install: - - ```sh - npm i @breadboard-ai/build-code - ``` - -2. Create a module with the following exports: - - - A type/interface called `Inputs` - - A type/interface called `Outputs` - - A function called `run` - - For example, the file `src/js-components/is-foo.ts`: - - ```ts - export interface Inputs { - str: string; - } - - export interface Outputs { - isFoo: boolean; - } - - export const run = ({ str }: Inputs): Outputs => { - return { isFoo: strIsFoo(str) }; - }; - - // Note that this function is outside the scope of `run`. This would - // normally be a problem with the the standard Breadboard `code` - // function, but it's OK here because we bundle! Imports work too. - function strIsFoo(str: string): boolean { - return str === "foo"; - } - ``` - -3. Use the `build-code` binary: - - ```json - { - "scripts": { - "generate:js-components": "build-code --tsconfig=./tsconfig.json --out=./src/generated ./src/js-components/*.ts" - } - } - ``` - -4. Import the generated module, which in this case will be at - `src/generated/is-foo.ts`, and use it with the Breadboard Build API. The - module will contain a strongly-typed function based on the name of the - source module: - - ```ts - import { isFoo } from "./generated/is-foo.js"; - import { input, board } from "@breadboard-ai/build"; - - const str = input(); - const isFooInst = isFoo({ str }); - export const myBoard = board({ - inputs: { str }, - outputs: { isFoo: isFooInst.outputs.isFoo }, - }); - ``` - -5. Upon serialization to BGL, a `runJavascript` component will be created - with bundled code and automatically generated schemas: - - ```json - { - "nodes": { - "id": "runJavascript-0", - "type": "runJavascript", - "configuration": { - "raw": true, - "name": "run", - "code": "export const run = ({ str }) => {\n return { isFoo: strIsFoo(str) };\n};\n\nfunction strIsFoo(str) {\n return str === \"foo\";\n}\n", - "inputSchema": { - "type": "object", - "properties": { - "str": { - "type": "string" - } - }, - "required": ["str"], - "additionalProperties": false - }, - "outputSchema": { - "type": "object", - "properties": { - "isFoo": { - "type": "boolean" - } - }, - "required": ["isFoo"], - "additionalProperties": false - } - } - } - } - ``` diff --git a/packages/build-code/bin/build-code b/packages/build-code/bin/build-code deleted file mode 100755 index 03a2ff4982d..00000000000 --- a/packages/build-code/bin/build-code +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env node - -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import "../dist/cli.js"; diff --git a/packages/build-code/package.json b/packages/build-code/package.json deleted file mode 100644 index 924510b0488..00000000000 --- a/packages/build-code/package.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "name": "@breadboard-ai/build-code", - "version": "0.1.0", - "description": "Convert TypeScript functions to Breadboard runJavascript components", - "license": "Apache-2.0", - "author": "Google LLC", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/build-code#readme", - "repository": { - "directory": "packages/build-code", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "bin": { - "build-code": "bin/build-code" - }, - "type": "module", - "main": "dist/index.js", - "typings": "dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "./index.js": { - "types": null, - "default": null - }, - "./internal/*.js": { - "types": "./dist/internal/*.d.ts", - "default": null - }, - "./*.js": { - "types": "./dist/*.d.ts", - "default": "./dist/*.js" - } - }, - "files": [ - "bin/*", - "dist/**/*.{js,js.map,d.ts}", - "!dist/test/", - "CHANGELOG.md" - ], - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "build:tsc": "wireit", - "test": "wireit", - "test:only": "wireit", - "lint": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "build:tsc", - "../build:build", - "../core-kit:build" - ] - }, - "build:tsc": { - "command": "tsc --pretty", - "dependencies": [ - "../build:build:tsc", - "../core-kit:build:tsc" - ], - "files": [ - "src/", - "tsconfig.json", - "package.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "test": { - "command": "find dist/test -name '*_test.js' | xargs node --test --enable-source-maps --test-reporter spec", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "test:only": { - "command": "find dist/test -name '*_test.js' | xargs node --test --test-only --enable-source-maps --test-reporter spec", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "lint": { - "command": "eslint src/ --ext .ts", - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - } - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@google-labs/core-kit": "^0.15.0", - "@types/node": "^22.0.0", - "esbuild": "^0.24.0", - "json-schema": "^0.4.0", - "json-schema-ref-parser": "^9.0.9", - "prettier": "^3.3.2", - "typescript-json-schema": "^0.65.1" - }, - "devDependencies": { - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" - } -} diff --git a/packages/build-code/src/cli.ts b/packages/build-code/src/cli.ts deleted file mode 100644 index 06b1353c9d5..00000000000 --- a/packages/build-code/src/cli.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { cp, mkdir, writeFile } from "node:fs/promises"; -import { basename, join } from "node:path"; -import { readConfigFromArgv } from "./config.js"; -import { generate } from "./generate.js"; - -const config = readConfigFromArgv(process.argv); -await mkdir(config.outputDir, { recursive: true }); - -// We don't want the user to need a production dependency on this package just -// so that the generated modules can import "support.ts", because it has large -// dependencies like esbuild. We could have a separate "support" package, but -// then we'd have to tell the user to install that. So, the simplest solution is -// just to copy the support library directly to the user's output folder. -const supportOutputPath = join(config.outputDir, "support.ts"); -console.log(`Writing support module to ${supportOutputPath}`); -await cp( - join(import.meta.dirname, "..", "src", "support.ts"), - supportOutputPath -); - -await Promise.all( - config.inputPaths.map(async (inputPath) => { - const generatedModuleSource = await generate(config, inputPath); - const outputPath = join(config.outputDir, basename(inputPath)); - console.log(`Writing generated module to ${outputPath}`); - await writeFile(outputPath, generatedModuleSource); - }) -); diff --git a/packages/build-code/src/config.ts b/packages/build-code/src/config.ts deleted file mode 100644 index 1f84eee71ea..00000000000 --- a/packages/build-code/src/config.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { resolve } from "node:path"; - -export interface Config { - inputPaths: string[]; - outputDir: string; - tsconfigPath: string; -} - -export function readConfigFromArgv(argv: string[]): Config { - const config: Config = { - inputPaths: [], - outputDir: "", - tsconfigPath: "", - }; - const seenFlags = new Set(); - for (const arg of argv.slice(2)) { - if (arg.startsWith("--")) { - const [flagName, flagValue] = arg.slice(2).split("=", 2); - if (!flagName || !flagValue) { - throw new Error(`Invalid flag: ${arg}`); - } - if (seenFlags.has(flagName)) { - throw new Error(`--${flagName} can only be specified once`); - } - seenFlags.add(flagName); - if (flagName === "out") { - config.outputDir = resolve(flagValue); - } else if (flagName === "tsconfig") { - config.tsconfigPath = resolve(flagValue); - } else { - throw new Error(`Unknown flag: ${flagName}`); - } - } else { - config.inputPaths.push(resolve(arg)); - } - } - if (!config.outputDir) { - throw new Error("--out is required"); - } - if (!config.tsconfigPath) { - throw new Error("--tsconfig is required"); - } - if (config.inputPaths.length === 0) { - throw new Error("At least one input file is required"); - } - return config; -} diff --git a/packages/build-code/src/generate.ts b/packages/build-code/src/generate.ts deleted file mode 100644 index c0135b3770c..00000000000 --- a/packages/build-code/src/generate.ts +++ /dev/null @@ -1,267 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as esbuild from "esbuild"; -import type { JSONSchema7 } from "json-schema"; -import RefParser from "json-schema-ref-parser"; -import { basename, relative } from "node:path"; -import * as prettier from "prettier"; -import * as tjs from "typescript-json-schema"; -import type { Config } from "./config.js"; - -export async function generate(config: Config, inputPath: string) { - const [code, schemas] = await Promise.all([ - bundleCode(inputPath), - extractSchemas(inputPath, config.tsconfigPath), - ]); - const generated = generateSource(code, schemas, inputPath, config.outputDir); - let formatted: string; - try { - formatted = await prettier.format(generated, { parser: "typescript" }); - } catch (e) { - throw new AggregateError( - [e], - `Error from prettier while formatting ${inputPath}` - ); - } - return formatted; -} - -async function bundleCode(inputPath: string): Promise { - const config: esbuild.BuildOptions = { - entryPoints: [inputPath], - format: "esm", - bundle: true, - write: false, - legalComments: "inline", - }; - let bundle; - try { - bundle = await esbuild.build(config); - } catch (e) { - throw new AggregateError( - [e], - `Error from esbuild with config ${JSON.stringify(config)}` - ); - } - for (const warning of bundle.warnings) { - console.warn( - `Warning from esbuild while bundling ${inputPath}: ` + - `${JSON.stringify(warning)}` - ); - } - if (bundle.errors.length > 0) { - throw new Error( - `Error bundling file ${inputPath}: ${JSON.stringify(bundle.errors)}` - ); - } - if (bundle.outputFiles === undefined || bundle.outputFiles.length !== 1) { - throw new Error( - `Error bundling file ${inputPath}: ` + - `Expected 1 output file, got ${bundle.outputFiles?.length ?? 0}.` - ); - } - return bundle.outputFiles[0]!.text; -} - -interface Schemas { - inputSchema: JSONSchema7; - outputSchema: JSONSchema7; -} - -export async function extractSchemas( - inputPath: string, - tsconfigPath: string -): Promise { - const tjsProgram = tjs.programFromConfig(tsconfigPath, [inputPath]); - const tjsConfig: tjs.PartialArgs = { - required: true, - skipLibCheck: true, - }; - let tjsGenerator; - try { - tjsGenerator = tjs.buildGenerator(tjsProgram, tjsConfig); - } catch (e) { - throw new AggregateError( - [e], - `Error from typescript-json-schema with config ${JSON.stringify(tjsConfig)}` - ); - } - if (tjsGenerator === null) { - throw new Error("Generator is null"); - } - - let inputSchema = tjsGenerator.getSchemaForSymbol("Inputs") as - | JSONSchema7 - | undefined; - let outputSchema = tjsGenerator.getSchemaForSymbol("Outputs") as - | JSONSchema7 - | undefined; - - if (inputSchema === undefined || outputSchema === undefined) { - throw new Error("Expected exported types called Inputs and Outputs"); - } - - // json-schema-ref-parser has a bug where it incorrectly parses certain refs, - // and then fails to look them up. - simplifyRefNames(inputSchema); - simplifyRefNames(outputSchema); - - // tjs generates $refs to refer to named types. To keep things simple, since - // we don't have great support for $refs in Breadboard yet, inline them all. - const refParserOptions: RefParser.Options = { - dereference: { - // Sometimes there are cycles in the schemas, and that's OK. In that case, - // the "ignore" option means it will preserve circular $refs but inline - // all the others. - circular: "ignore", - }, - }; - try { - inputSchema = (await RefParser.default.dereference( - inputSchema, - refParserOptions - )) as JSONSchema7; - } catch (e) { - throw new AggregateError( - [e], - `Error from json-schema-ref-parser with schema ${JSON.stringify(inputSchema)}` - ); - } - try { - outputSchema = (await RefParser.default.dereference( - outputSchema, - refParserOptions - )) as JSONSchema7; - } catch (e) { - throw new AggregateError( - [e], - `Error from json-schema-ref-parser with schema ${JSON.stringify(outputSchema)}` - ); - } - - // A little cleanup. - delete inputSchema["$schema"]; - delete outputSchema["$schema"]; - cleanUpDefinitions(inputSchema); - cleanUpDefinitions(outputSchema); - - return { inputSchema, outputSchema }; -} - -function generateSource( - bundledCode: string, - { inputSchema, outputSchema }: Schemas, - inputPath: string, - outputDir: string -): string { - const sourceImportSpecifier = relative(outputDir, inputPath).replace( - /\.ts$/, - ".js" - ); - const functionName = kebabToCamel(basename(inputPath).replace(/\.ts/, "")); - return ` - import {makeRunJavascriptComponent} from "./support.js"; - import type {Inputs, Outputs} from "${sourceImportSpecifier}"; - - /** - * This function was generated by @breadboard-ai/build-code from - * ${relative(process.cwd(), inputPath)} - */ - export const ${functionName} = makeRunJavascriptComponent({ - code: \`${escapeForTemplateLiteral(bundledCode)}\`, - inputSchema: ${JSON.stringify(inputSchema)}, - outputSchema: ${JSON.stringify(outputSchema)}, - }); - `; -} - -function kebabToCamel(kebab: string): string { - return kebab - .toLowerCase() - .replace(/[-_][a-z]/g, (group) => group.slice(-1).toUpperCase()); -} - -function escapeForTemplateLiteral(str: string): string { - return str.replace(/`/g, "\\`").replace(/\${/g, "\\${"); -} - -const DEFINITIONS_PREFIX = "#/definitions/"; - -/** - * Replace all $refs with a simple unique name. - */ -function simplifyRefNames(root: JSONSchema7) { - if (root.definitions === undefined) { - return; - } - - const aliases = new Map(); - let nextId = 0; - - for (const [oldName, def] of Object.entries(root.definitions)) { - const newName = `def-${nextId++}`; - aliases.set(DEFINITIONS_PREFIX + oldName, DEFINITIONS_PREFIX + newName); - root.definitions[newName] = def; - delete root.definitions[oldName]; - } - if (aliases.size === 0) { - return; - } - - const visit = (schema: JSONSchema7) => { - if (Array.isArray(schema)) { - for (const item of schema) { - visit(item); - } - } else if (typeof schema === "object" && schema !== null) { - for (const val of Object.values(schema)) { - visit(val); - } - if (schema.$ref !== undefined) { - const alias = aliases.get(schema.$ref); - if (alias !== undefined) { - schema.$ref = alias; - } - } - } - }; - visit(root); -} - -/** - * Remove any `definitions` that aren't referenced in the schema, and then if - * there are none left, remove `definitions` all together. - */ -function cleanUpDefinitions(root: JSONSchema7) { - if (root.definitions === undefined) { - return; - } - const usedRefs = new Set(); - const visit = (schema: JSONSchema7) => { - if (Array.isArray(schema)) { - for (const item of schema) { - visit(item); - } - } else if (typeof schema === "object" && schema !== null) { - for (const val of Object.values(schema)) { - visit(val); - } - if (schema.$ref !== undefined) { - usedRefs.add(schema.$ref); - } - } - }; - visit(root); - for (const ref of Object.keys(root.definitions)) { - if (!usedRefs.has(DEFINITIONS_PREFIX + ref)) { - delete root.definitions[ref]; - } - } - if (Object.keys(root.definitions).length === 0) { - delete root.definitions; - } -} diff --git a/packages/build-code/src/support.ts b/packages/build-code/src/support.ts deleted file mode 100644 index 71838e22322..00000000000 --- a/packages/build-code/src/support.ts +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { Definition, Value } from "@breadboard-ai/build"; -import { unsafeType, type JsonSerializable } from "@breadboard-ai/build"; -import { runJavascript } from "@google-labs/core-kit"; -import type { JSONSchema4, JSONSchema7 } from "json-schema"; - -export interface MakeCodeComponentParams { - code: string; - inputSchema: JSONSchema7; - outputSchema: JSONSchema7; -} - -/** - * Instantiates a `runJavascript` component instance suitable for use with the - * Build API. - * - * This function is intended for use only by the modules that are generated by - * build-code. - */ -export function makeRunJavascriptComponent< - I extends Record, - O extends Record, ->({ code, inputSchema, outputSchema }: MakeCodeComponentParams) { - type ThisDefinition = Definition< - I, - O, - undefined, - undefined, - never, - false, - false, - false, - never - >; - type ThisArgs = Parameters[0]; - type ThisInstance = ReturnType; - return (args: ThisArgs): ThisInstance => { - const instance = runJavascript({ - ...(args as Record), - code, - name: "run", - raw: true, - // TODO(aomarks) Upgrade to the JSONSchema7 type everywhere. - inputSchema: inputSchema as object as JSONSchema4, - outputSchema: outputSchema as object as JSONSchema4, - }); - // TODO(aomarks) We should have a proper API for this. We're initializing - // the ports and setting their schemas. - for (const [name, schema] of Object.entries( - outputSchema.properties ?? {} - )) { - const port = instance.unsafeOutput(name); - (port as Writable).type = unsafeType( - schema as object as JSONSchema4 - ); - (instance.outputs as Record)[name] = port; - } - return instance as object as ThisInstance; - }; -} - -type Writable = { -readonly [P in keyof T]: T[P] }; diff --git a/packages/build-code/src/test/config_test.ts b/packages/build-code/src/test/config_test.ts deleted file mode 100644 index 4c2316d4b8b..00000000000 --- a/packages/build-code/src/test/config_test.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { readConfigFromArgv, type Config } from "../config.js"; -import { join } from "node:path"; - -function resolved(path: string): string { - return join(import.meta.dirname, "..", "..", path); -} - -test("read config", () => { - assert.deepEqual( - readConfigFromArgv([ - "node", - "script", - "--tsconfig=path/to/tsconfig.json", - "--out=path/to/out/dir", - "path/to/foo.ts", - "path/to/bar.ts", - ]), - { - inputPaths: [resolved("path/to/foo.ts"), resolved("path/to/bar.ts")], - outputDir: resolved("path/to/out/dir"), - tsconfigPath: resolved("path/to/tsconfig.json"), - } satisfies Config - ); -}); diff --git a/packages/build-code/src/test/extract-schemas_test.ts b/packages/build-code/src/test/extract-schemas_test.ts deleted file mode 100644 index b61c7724880..00000000000 --- a/packages/build-code/src/test/extract-schemas_test.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { join } from "node:path"; -import { test } from "node:test"; -import { extractSchemas } from "../generate.js"; -import { testDataDir } from "./test-data-dir.js"; - -test("breadboard type expression", async () => { - const actual = await extractSchemas( - join(testDataDir, "breadboard-type-expression.ts"), - join(testDataDir, "tsconfig.json") - ); - const expected = { - inputSchema: { - type: "object", - properties: { - strArr: { type: "array", items: { type: "string" } }, - }, - required: ["strArr"], - }, - outputSchema: { - type: "object", - properties: { - strArr: { type: "array", items: { type: "string" } }, - }, - required: ["strArr"], - }, - }; - assert.deepEqual(actual, expected); -}); - -test("type in other file", async () => { - const actual = await extractSchemas( - join(testDataDir, "type-in-other-file.ts"), - join(testDataDir, "tsconfig.json") - ); - const expected = { - inputSchema: { - type: "object", - properties: { - boolArr: { type: "array", items: { type: "boolean" } }, - }, - required: ["boolArr"], - }, - outputSchema: { - type: "object", - properties: { - boolArr: { type: "array", items: { type: "boolean" } }, - }, - required: ["boolArr"], - }, - }; - assert.deepEqual(actual, expected); -}); diff --git a/packages/build-code/src/test/generate_test.ts b/packages/build-code/src/test/generate_test.ts deleted file mode 100644 index 154bb186ff9..00000000000 --- a/packages/build-code/src/test/generate_test.ts +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { board, input, serialize } from "@breadboard-ai/build"; -import assert from "node:assert/strict"; -import { readFile } from "node:fs/promises"; -import { join } from "node:path"; -import { test } from "node:test"; -import type { Config } from "../config.js"; -import { generate } from "../generate.js"; -import { testDataDir } from "./test-data-dir.js"; - -test("generates module", async () => { - const fooPath = join(testDataDir, "str-is-foo.ts"); - const config: Config = { - inputPaths: [fooPath], - outputDir: join(testDataDir, "out"), - tsconfigPath: join(testDataDir, "tsconfig.json"), - }; - const actual = await generate(config, fooPath); - const expected = await readFile( - join(testDataDir, "generated", "str-is-foo.ts"), - "utf8" - ); - assert.equal(actual, expected); -}); - -test("serializes to BGL", async () => { - const { strIsFoo } = await import("./testdata/generated/str-is-foo.js"); - const str = input(); - const fooInst = strIsFoo({ - str, - numArr: [1, 2, 3], - deepObj: { foo: { bar: "bar" } }, - }); - const myBoard = board({ - inputs: { str }, - outputs: { isFoo: fooInst.outputs.bool }, - }); - const actual = serialize(myBoard); - const expected = { - edges: [ - { from: "input-0", to: "runJavascript-0", out: "str", in: "str" }, - { from: "runJavascript-0", to: "output-0", out: "bool", in: "isFoo" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { str: { type: "string" } }, - required: ["str"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { isFoo: { type: "boolean" } }, - required: ["isFoo"], - }, - }, - }, - { - id: "runJavascript-0", - type: "runJavascript", - configuration: { - raw: true, - name: "run", - code: `// src/test/testdata/util.ts -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -function strIsFoo(str) { - return str === "foo"; -} - -// src/test/testdata/str-is-foo.ts -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -var run = ({ str }) => { - return { bool: strIsFoo(str) }; -}; -export { - run -}; -`, - numArr: [1, 2, 3], - deepObj: { foo: { bar: "bar" } }, - inputSchema: { - type: "object", - properties: { - str: { type: "string" }, - opt: { type: "string" }, - numArr: { type: "array", items: { type: "number" } }, - deepObj: { - type: "object", - properties: { - foo: { - type: "object", - properties: { bar: { type: "string" } }, - required: ["bar"], - }, - }, - required: ["foo"], - }, - }, - required: ["deepObj", "numArr", "str"], - }, - outputSchema: { - type: "object", - properties: { - bool: { type: "boolean" }, - opt: { type: "string" }, - }, - required: ["bool"], - }, - }, - }, - ], - }; - assert.deepEqual(actual, expected); -}); diff --git a/packages/build-code/src/test/test-data-dir.ts b/packages/build-code/src/test/test-data-dir.ts deleted file mode 100644 index 0fc4edf8b55..00000000000 --- a/packages/build-code/src/test/test-data-dir.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { join } from "path"; - -export const testDataDir = join( - import.meta.dirname, - "..", - "..", - "src", - "test", - "testdata" -); diff --git a/packages/build-code/src/test/testdata/breadboard-type-expression.ts b/packages/build-code/src/test/testdata/breadboard-type-expression.ts deleted file mode 100644 index bc430cd5092..00000000000 --- a/packages/build-code/src/test/testdata/breadboard-type-expression.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { array, type ConvertBreadboardType } from "@breadboard-ai/build"; - -const strArr = array("string"); -type StrArr = ConvertBreadboardType; - -export type Inputs = { - strArr: StrArr; -}; - -export type Outputs = { - strArr: StrArr; -}; - -export const run = ({ strArr }: Inputs): Outputs => { - return { strArr }; -}; diff --git a/packages/build-code/src/test/testdata/generated/str-is-foo.ts b/packages/build-code/src/test/testdata/generated/str-is-foo.ts deleted file mode 100644 index 64a6fdf50da..00000000000 --- a/packages/build-code/src/test/testdata/generated/str-is-foo.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { makeRunJavascriptComponent } from "./support.js"; -import type { Inputs, Outputs } from "../str-is-foo.js"; - -/** - * This function was generated by @breadboard-ai/build-code from - * src/test/testdata/str-is-foo.ts - */ -export const strIsFoo = makeRunJavascriptComponent({ - code: `// src/test/testdata/util.ts -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -function strIsFoo(str) { - return str === "foo"; -} - -// src/test/testdata/str-is-foo.ts -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -var run = ({ str }) => { - return { bool: strIsFoo(str) }; -}; -export { - run -}; -`, - inputSchema: { - type: "object", - properties: { - str: { type: "string" }, - opt: { type: "string" }, - numArr: { type: "array", items: { type: "number" } }, - deepObj: { - type: "object", - properties: { - foo: { - type: "object", - properties: { bar: { type: "string" } }, - required: ["bar"], - }, - }, - required: ["foo"], - }, - }, - required: ["deepObj", "numArr", "str"], - }, - outputSchema: { - type: "object", - properties: { bool: { type: "boolean" }, opt: { type: "string" } }, - required: ["bool"], - }, -}); diff --git a/packages/build-code/src/test/testdata/generated/support.ts b/packages/build-code/src/test/testdata/generated/support.ts deleted file mode 120000 index 1de1f6a6adb..00000000000 --- a/packages/build-code/src/test/testdata/generated/support.ts +++ /dev/null @@ -1 +0,0 @@ -../../../support.ts \ No newline at end of file diff --git a/packages/build-code/src/test/testdata/str-is-foo.ts b/packages/build-code/src/test/testdata/str-is-foo.ts deleted file mode 100644 index adf76bdd23a..00000000000 --- a/packages/build-code/src/test/testdata/str-is-foo.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { strIsFoo } from "./util.js"; - -export type Inputs = { - str: string; - opt?: string; - numArr: number[]; - deepObj: { foo: { bar: string } }; -}; - -export type Outputs = { - bool: boolean; - opt?: string; -}; - -export const run = ({ str }: Inputs): Outputs => { - return { bool: strIsFoo(str) }; -}; diff --git a/packages/build-code/src/test/testdata/tsconfig.json b/packages/build-code/src/test/testdata/tsconfig.json deleted file mode 100644 index 6664397a4f5..00000000000 --- a/packages/build-code/src/test/testdata/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "lib": ["ES2022", "DOM"] - }, - "include": ["**/*.ts"], - "exclude": [] -} diff --git a/packages/build-code/src/test/testdata/type-in-other-file.ts b/packages/build-code/src/test/testdata/type-in-other-file.ts deleted file mode 100644 index 6e6dfa0a444..00000000000 --- a/packages/build-code/src/test/testdata/type-in-other-file.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { BoolArr } from "./util.js"; - -export type Inputs = { - boolArr: BoolArr; -}; - -export type Outputs = { - boolArr: BoolArr; -}; - -export const run = ({ boolArr }: Inputs): Outputs => { - return { boolArr }; -}; diff --git a/packages/build-code/src/test/testdata/util.ts b/packages/build-code/src/test/testdata/util.ts deleted file mode 100644 index 357f2f022c8..00000000000 --- a/packages/build-code/src/test/testdata/util.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export function strIsFoo(str: string): boolean { - return str === "foo"; -} - -export type BoolArr = boolean[]; diff --git a/packages/build-code/tsconfig.json b/packages/build-code/tsconfig.json deleted file mode 100644 index 4c0109444dd..00000000000 --- a/packages/build-code/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/.tsbuildinfo", - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "types": ["node"], - "lib": ["ES2022", "DOM"], - "incremental": true, - "declaration": true, - "sourceMap": true, - "inlineSources": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "noImplicitOverride": true, - "noUncheckedIndexedAccess": true, - "verbatimModuleSyntax": true, - "useUnknownInCatchVariables": true - }, - "include": ["src/**/*.ts"], - "exclude": [] -} diff --git a/packages/build/.eslintrc b/packages/build/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/build/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/build/CHANGELOG.md b/packages/build/CHANGELOG.md deleted file mode 100644 index c54d0e3155d..00000000000 --- a/packages/build/CHANGELOG.md +++ /dev/null @@ -1,443 +0,0 @@ -# Changelog - -## 0.10.0 - -### Minor Changes - -- 54c8197: Make build API kit function async -- 8540b93: Convert Content to Build API and merge Specialist 2 to Specialist. - -### Patch Changes - -- 49e2740: Allow passing a raw GraphDescriptor to Build API kit function -- 2f1b85c: When wiring star output to a node, the input port needs to be empty string instead of star. -- c145fdd: Add bubble parameter to outputNode function -- 226be62: Support logLevel metadata -- 2fa05f0: Export some additional types -- f71bcfb: Add a Breadboard Type Expression to represent JSON schema itself. - - For now this is using our Schema type, and a generic object schema - with the json-schema behavior. In the future we can switch this to - the official JSON Schema types, and a {$ref} schema for the official - JSON Schema schema. - -- 3188607: Get titles/descriptions from either metadata or toplevel -- 8330f0c: Add rawInput function -- 1423647: Fix incorrect JSON Schema for jsonSchema -- 6cdf20c: The anyOf function now hoists out any common "type" it finds, to help with code in breadboard that assumes there is always a top-level type (e.g. when visual editor looks for llm-content). -- f63a497: Fix incorrect position of deprecated behavior -- 91fe8bb: Allow annotating output ports as deprecated -- 100fc95: Various fixes and polish. -- cab83ce: Allow wiring up a board's $error -- e19f046: Allow setting $id and $metadata when initializing a board instance -- 5834c81: Components imported through kit objects are now serialized directly with "type" instead of via an invoke node. -- 0ef793f: Export ConvertBreadboardType utility -- Updated dependencies [703f17d] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [4dadf16] -- Updated dependencies [8f9fddf] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [9797718] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [a039d2e] -- Updated dependencies [9783ba8] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [d7606d3] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] - - @google-labs/breadboard@0.27.0 - -## 0.9.1 - -### Patch Changes - -- bbcdd2d: Ensure descriptions survive kitification -- 9ed58cf: Add starInputs function to get a handle on the "\*" input port of a board -- 7f2ef33: Improve generated typings of legacy api bridge function -- bac2e35: Adds a legacy() function to the result of calling kit(). It's a function that asynchronously returns a kit that is automatically built with and type for the old API, allowing new API kits to be used directly in old boards. -- ec2fedd: Improvements to the describe() behavior of boards built with the Build API that are polymorphic. -- Updated dependencies [7d46a63] - - @google-labs/breadboard@0.26.0 - -## 0.9.0 - -### Minor Changes - -- cc5f4b6: Changes to the signature of the board function. Introduces new inputNode and outputNode functions which are used for polymorphic boards. -- a940b87: The kit function now takes components as an object instead of an array. -- 7de241c: Remove `BoardRunner`. - -### Patch Changes - -- 374ea85: Internal refactoring (branding) -- f93ec06: Reflect when an input is optional by making its type parameter possibly undefined. -- 398bf4f: Behaviors added with the annotate function are now additive instead of clobbery. -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @google-labs/breadboard@0.25.0 - -## 0.8.1 - -### Patch Changes - -- d88c37b: Add support for JSON Schema string formatting options with a new `string` function that takes an options object with format, pattern, minLength, and maxLength. -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [1dc645a] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [c04cff0] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - -## 0.8.0 - -### Minor Changes - -- 2312443: Add support for `deprecated` and `experimental` tags on Kits. - -### Patch Changes - -- ad8aa22: Add kit function to build for making kits -- f78ec0a: Add intersect function to breadboard type expressions system for intersecting two objects -- b76f9a1: Add id, metadata, and breadboardType to component definition classes -- 15ae381: Fix optional output serialization -- Updated dependencies [1e1be2a] -- Updated dependencies [2b094a3] -- Updated dependencies [fa93c3f] -- Updated dependencies [215bd15] -- Updated dependencies [2b9ef5b] -- Updated dependencies [a0852df] -- Updated dependencies [2312443] -- Updated dependencies [6ffa89c] - - @google-labs/breadboard@0.23.0 - -## 0.7.1 - -### Patch Changes - -- da43bb5: Allow wiring inputs directly to outputs -- 5cf08f1: Add "wires" property to NodeDescriberContext which exposes a describe() function for getting the actual schema of a connected port if needed. -- 9d93cf8: Fix bug relating to directly returning JSON Schema from describe function instead of wrapping with unsafeSchema. -- 26e1099: Add describe function to Board component class -- Updated dependencies [a925cf0] -- Updated dependencies [5cf08f1] -- Updated dependencies [ffbf163] -- Updated dependencies [8928fb7] -- Updated dependencies [d6706f2] -- Updated dependencies [5447426] -- Updated dependencies [7e1f01c] - - @google-labs/breadboard@0.22.0 - -## 0.7.0 - -### Minor Changes - -- 14853d5: Add Gemini Nano node. -- 6ada218: Input ports with the "board" behavior can now receive board objects declared using the build API. This will be serialized as an embedded graph. -- 2ace620: Teach `InspectableGraph.describe` to correctly propagate fixed/flexible bit. - -### Patch Changes - -- 00825d5: Can now pass metadata to board function -- c5f8e4f: Teach BreadboardError about BreadboardCapability. -- 06c3f57: Add optionalEdge function which marks an edge optional. -- Updated dependencies [5a55b7d] -- Updated dependencies [74ade20] -- Updated dependencies [59dd0f5] -- Updated dependencies [417323c] -- Updated dependencies [b3aa884] -- Updated dependencies [3d7b4a7] -- Updated dependencies [7af14cf] -- Updated dependencies [fea8967] -- Updated dependencies [778f7aa] -- Updated dependencies [808f5e2] -- Updated dependencies [e0fdbc3] -- Updated dependencies [54b03b9] -- Updated dependencies [810d7fd] -- Updated dependencies [14853d5] -- Updated dependencies [8798514] -- Updated dependencies [eb64b9a] -- Updated dependencies [32a48a3] -- Updated dependencies [cd73b17] -- Updated dependencies [81d82fe] -- Updated dependencies [2a7531b] -- Updated dependencies [7c1b4cb] -- Updated dependencies [702cfe1] -- Updated dependencies [bebd96e] -- Updated dependencies [91cb723] -- Updated dependencies [3e10f0f] -- Updated dependencies [c53ca01] -- Updated dependencies [4c681cb] -- Updated dependencies [fb2e584] -- Updated dependencies [9491266] -- Updated dependencies [2ace620] -- Updated dependencies [fcef799] -- Updated dependencies [37418d9] -- Updated dependencies [083f69c] -- Updated dependencies [5b03d96] -- Updated dependencies [f0d8d67] -- Updated dependencies [836389d] -- Updated dependencies [225c7cc] - - @google-labs/breadboard@0.21.0 - -## 0.6.0 - -### Minor Changes - -- f97a4d5: Rename "placeholder" to "loopback". - -### Patch Changes - -- 29eda71: Board outputs can now be an array of output node configurations -- f60cb06: Set the "type" field when an enumeration is all of one type. -- 87eb8fe: Stringify all defaults and examples -- 60a18c5: Don't make input ports required if there is a default -- b0ed6f3: Allow converge function to take raw values -- 4957dc5: Improve handling of defaults in describe functions. Defaults are now always passed into the describe function, and types will be optional or not based on whether there is a default (default means it can never be undefined). -- a209c51: Use actual schema when auto-computing input schema -- 7368fdd: Allow inputs to be constant -- c9c0e06: Allow declaring objects with optional properties -- c1acf24: Add converge function which allows wiring multiple edges to the same input port -- 3920805: Allow inputs to be optional -- 3b2bb4a: Fix type system bug relating to primary input/output ports (it wasn't working quite right when there were more than one input or output ports). -- 31cf016: Fix a bug in the @breadboard-ai/build type system that allowed node instances to be passed as board outputs even if they did not have a primary port. -- ab43276: Fix bug where constant wouldn't always preserve type information -- 477e6e6: Sort more schema fields for easier comparison across serializers -- cdcbcdb: Node invoke functions can now return $error. All node instances now automatically have an outputs.$error. Throwing from an invoke function will now convert the exception to an $error result; the stack trace is logged to the server, but not shown to the end-user. -- 791ec2a: Add `constant` function which can be used to annotate edges that should get the `constant` bit (also known as memoize). -- c0293c9: New syntax for declaring multiple inputs along with metadata -- b6f5644: Surface a stack trace when an exception is thrown -- 43edef6: Add support for setting $metadata when instantiating a node -- Updated dependencies [8097177] -- Updated dependencies [cec6d54] -- Updated dependencies [3397974] -- Updated dependencies [ab9a4ce] -- Updated dependencies [a35406c] -- Updated dependencies [477e6e6] - - @google-labs/breadboard@0.20.0 - -## 0.5.1 - -### Patch Changes - -- Updated dependencies [63eb779] - - @google-labs/breadboard@0.19.0 - -## 0.5.0 - -### Minor Changes - -- 55a9647: Rename assertOutput to unsafeOutput -- 1adb24c: Replace multiline field with format, which can be multiline or javascript -- d9ac358: Convert secrets node to use @breadboard-ai/build. No functional difference, but the JSON schema should be slightly stricter. -- 1e86a87: Allow object types to have additional properties. Additional properties are now disabled by default. - -### Patch Changes - -- 3f9507d: The breadboard type expression object({}) is now more strictly constrained to plain objects (rather than anything). -- 1e86a87: Add enumeration type -- 3f9507d: Simpler JSON schema serialization for array -- 1adb24c: additionalProperties is now set on generated port JSON schemas -- 1e86a87: Add support for default values on static inputs -- fefd109: JSON schema for outputs no longer sets any required properties -- c1dcb0a: Make serialization order more similar to existing one -- 416aed2: Introduce `metadata` for `NodeHandler` entries, teaching node types in Kits to describe themselves. -- f1883d1: Add an output function for customizing a board's output node layout -- 1adb24c: Inbound edges, even if they don't have a value, now inform the auto generated input schema -- d8cb0c9: Add unsafeCast function as an escape hatch for when an output doesn't match a type but you're really really sure it's ok -- 34d9c6d: Generated JSON schemas are now more explicit and verbose -- e6e0168: Allow describe functions to be async -- 1adb24c: Fix some incorrect type errors from certain describe functions. -- 3f9507d: The describe function can now return objects with new descriptions -- 1adb24c: Automatically detected input ports are no longer required. Only static ones. -- 3f9507d: Add multiline option to port config -- c4ca6dc: Allow setting node IDs -- 1adb24c: Allow specifying behaviors -- cfbcdf2: Pass NodeHandlerContext to invoke functions -- 1d9cb16: Inputs can now have examples -- 49da151: Allow setting id on inputs, which can be used to customize the input node id, - or to create multiple input nodes. If two input objects reference the same - id, then they will both be placed into a BGL input node with that ID. If no - id is specified, the usual "input-0" is used. -- 3f9507d: Simpler JSON schema serialization for anyOf -- dfd5ce2: Input ports can now be marked as optional. -- cfc0f15: Add support for input titles -- 00ccb9d: Add unsafeSchema function which allows returning raw arbitrary JSON schema from a describe function -- 08eabf4: Title, description, and version are now included in BGL -- 99fcffe: describe function now receives a NodeDescriberContext -- d9ac358: Add ability to override default port title -- Updated dependencies [cef20ca] -- Updated dependencies [fbf7a83] -- Updated dependencies [54baba8] -- Updated dependencies [49c3aa1] -- Updated dependencies [cdc23bb] -- Updated dependencies [416aed2] -- Updated dependencies [a1fcaea] -- Updated dependencies [c3ed6a7] -- Updated dependencies [3d48482] -- Updated dependencies [f2eda0b] -- Updated dependencies [626139b] -- Updated dependencies [bd44e29] -- Updated dependencies [43da00a] -- Updated dependencies [c3587e1] -- Updated dependencies [3f9507d] - - @google-labs/breadboard@0.18.0 - -## 0.4.0 - -### Minor Changes - -- de524a4: Change the describe function to return only the names of ports instead of full JSON schema, and be stricter about when it is required/optional/forbidden based on the port configurations. - -### Patch Changes - -- de524a4: Improved type-safety and type descriptions relating to node definitions. -- de524a4: Add support for reflective nodes, where the inputs provided at instantiation automatically reflect to outputs. -- de524a4: Add `assertOutput` method, for getting an output port in cases where it is not possible at compile-time to know what output ports will exist. -- de524a4: Add support for polymorphic nodes with dynamic output ports. -- Updated dependencies [c3cb25f] -- Updated dependencies [ae79e4a] -- Updated dependencies [72c5c6b] -- Updated dependencies [dd810dd] -- Updated dependencies [c5ba396] -- Updated dependencies [7bafa40] -- Updated dependencies [2932f4b] -- Updated dependencies [51159c4] -- Updated dependencies [6f9ba52] - - @google-labs/breadboard@0.17.0 - -## 0.3.1 - -### Patch Changes - -- Updated dependencies [ad9c233] -- Updated dependencies [65d869b] -- Updated dependencies [417cdf5] -- Updated dependencies [cf0ee4f] -- Updated dependencies [43cbed7] -- Updated dependencies [ff6433c] -- Updated dependencies [5382365] -- Updated dependencies [0e7f106] -- Updated dependencies [9ea6ba0] -- Updated dependencies [ffd2a6c] - - @google-labs/breadboard@0.16.0 - -## 0.3.0 - -### Minor Changes - -- 4de92a3: Add placeholder() function, useful for representing cycles. - -### Patch Changes - -- Updated dependencies [76da09d] -- Updated dependencies [938015d] - - @google-labs/breadboard@0.15.0 - -## 0.2.0 - -### Minor Changes - -- 7949ec9: Make "name" required when defining nodes, so that they can always be serialized -- da2e263: Add new board function for creating boards, and serialize for making BGL from them - -### Patch Changes - -- 949bce7: Add a Value type which can represent a value or a stand-in for a value (output port, input object, etc.) -- Updated dependencies [e8d0737] - - @google-labs/breadboard@0.14.0 - -## 0.1.2 - -### Patch Changes - -- Updated dependencies [faf1e12] -- Updated dependencies [51a38c0] -- Updated dependencies [d49b80e] -- Updated dependencies [9326bd7] -- Updated dependencies [fbad949] - - @google-labs/breadboard@0.13.0 - -## 0.1.1 - -### Patch Changes - -- fe6b8de: Fix missing build artifacts - -## 0.1.0 - -### Minor Changes - -- 6a0bbbf: Initial release of @breadboard-ai/build - -## 0.0.1 - -### Patch Changes - -- Updated dependencies [99446b8] -- Updated dependencies [866fc36] -- Updated dependencies [a8bab08] -- Updated dependencies [decfa29] -- Updated dependencies [f005b3b] -- Updated dependencies [dcfdc37] -- Updated dependencies [d971aad] -- Updated dependencies [048e8ec] -- Updated dependencies [dc35601] -- Updated dependencies [9cda2ff] -- Updated dependencies [60bd63c] -- Updated dependencies [764ccda] -- Updated dependencies [04d5420] -- Updated dependencies [56b90a4] -- Updated dependencies [1b48826] -- Updated dependencies [e648f64] -- Updated dependencies [ad5c1be] -- Updated dependencies [4a4a1f6] -- Updated dependencies [bac9bb1] -- Updated dependencies [3e8cfcf] -- Updated dependencies [986af39] -- Updated dependencies [3c497b0] -- Updated dependencies [eabd97b] -- Updated dependencies [2008f69] -- Updated dependencies [c0f785a] -- Updated dependencies [a8fc3f3] -- Updated dependencies [32cfbaf] -- Updated dependencies [8dc4e00] -- Updated dependencies [6438930] -- Updated dependencies [dd2cce6] -- Updated dependencies [cac4f4f] -- Updated dependencies [b1fc53b] -- Updated dependencies [ef05634] -- Updated dependencies [c208cfc] - - @google-labs/breadboard@0.12.0 diff --git a/packages/build/README.md b/packages/build/README.md deleted file mode 100644 index 5dc8fdc4c61..00000000000 --- a/packages/build/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# Breadboard Build - -[![Published on npm](https://img.shields.io/npm/v/@breadboard-ai/build.svg?logo=npm)](https://www.npmjs.com/package/@breadboard-ai/build) - -The Breadboard Build API allows you to design and compose boards with -[TypeScript](https://www.typescriptlang.org/). - -It is an alternative to the Visual Editor, designed for users who prefer a -code-first approach to working with Breadboard. - -Boards that you create with the Build API can be serialized to BGL (Breadboard -Graph Language), which can then be executed directly, or imported into the -Visual Editor. - -## Install - -```sh -npm i @breadboard-ai/build -``` - -## Documentation - -Please refer to the [Build -API](https://breadboard-ai.github.io/breadboard/docs/build/) section of the -Breadboard Documentation site for full documentation. - -## Example - -```ts -import { board, input, output } from "@breadboard-ai/build"; -import { prompt } from "@google-labs/template-kit"; -import { geminiText } from "@google-labs/gemini-kit"; - -const topic = input({ - description: "What should the poem be about?", - examples: ["Coffee in the morning", "The mind of a cat"], -}); - -const stanzas = input({ - type: "number", - description: "How many stanzas should the poem have?", - default: 4, -}); - -const poemPrompt = prompt` - Write a poem about ${topic} with ${stanzas} stanzas.`; - -const poemWriter = geminiText({ - text: poemPrompt, - model: "gemini-1.5-flash-latest", -}); - -const poem = output(poemWriter.outputs.text, { - title: "Poem", - description: "The poem that Gemini generated.", -}); - -export default board({ - id: "poem-writer", - title: "Poem Writer", - description: "Write a poem with Gemini.", - inputs: { topic, stanzas }, - outputs: { poem }, -}); -``` diff --git a/packages/build/package.json b/packages/build/package.json deleted file mode 100644 index 423ddc09a19..00000000000 --- a/packages/build/package.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "name": "@breadboard-ai/build", - "version": "0.10.0", - "description": "JavaScript library for building boards and defining new node types for the Breadboard AI prototyping library", - "license": "Apache-2.0", - "author": "Google LLC", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/build#readme", - "repository": { - "directory": "packages/build", - "type": "git", - "url": "git+https://github.com/breadboard-ai/build.git" - }, - "type": "module", - "main": "dist/index.js", - "typings": "dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "./index.js": { - "types": null, - "default": null - }, - "./internal/*.js": { - "types": "./dist/internal/*.d.ts", - "default": null - }, - "./*.js": { - "types": "./dist/*.d.ts", - "default": "./dist/*.js" - } - }, - "files": [ - "dist/**/*.{js,js.map,d.ts}", - "!dist/test/", - "CHANGELOG.md" - ], - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "build:tsc": "wireit", - "test": "wireit", - "test:only": "wireit", - "coverage": "wireit", - "lint": "wireit", - "test-and-lint": "wireit", - "dev": "npm run test-and-lint --watch" - }, - "wireit": { - "build": { - "dependencies": [ - "build:tsc", - "../breadboard:build" - ] - }, - "build:tsc": { - "command": "tsc --pretty", - "dependencies": [ - "../breadboard:build:tsc" - ], - "files": [ - "src/", - "tsconfig.json", - "package.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "test": { - "command": "find dist/test -name '*_test.js' | xargs node --test --enable-source-maps --test-reporter spec", - "dependencies": [ - "build:tsc", - "../core-kit:build:tsc" - ], - "files": [], - "output": [] - }, - "test:only": { - "command": "find dist/test -name '*_test.js' | xargs node --test --test-only --enable-source-maps --test-reporter spec", - "dependencies": [ - "build:tsc", - "../core-kit:build:tsc" - ], - "files": [], - "output": [] - }, - "coverage": { - "command": "find dist/test -name '*_test.js' | xargs node --test --enable-source-maps --experimental-test-coverage --test-reporter lcov --test-reporter-destination=lcov.info", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [ - "lcov.info" - ] - }, - "lint": { - "command": "eslint src/ --ext .ts", - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - }, - "test-and-lint": { - "dependencies": [ - "test", - "lint" - ] - } - }, - "dependencies": { - "@google-labs/breadboard": "^0.27.0", - "@types/json-schema": "^7.0.15" - }, - "devDependencies": { - "@types/node": "^22.0.0", - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" - } -} diff --git a/packages/build/src/index.ts b/packages/build/src/index.ts deleted file mode 100644 index 6965a2aea21..00000000000 --- a/packages/build/src/index.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export { board, inputNode, outputNode } from "./internal/board/board.js"; -export { constant } from "./internal/board/constant.js"; -export { converge } from "./internal/board/converge.js"; -export { input, rawInput } from "./internal/board/input.js"; -export { loopback } from "./internal/board/loopback.js"; -export { optionalEdge } from "./internal/board/optional.js"; -export { output } from "./internal/board/output.js"; -export { serialize } from "./internal/board/serialize.js"; -export { starInputs } from "./internal/board/star-inputs.js"; -export { unsafeCast } from "./internal/board/unsafe-cast.js"; -export { - // TODO() Not quite sure about exporting and/or the name of - // SerializableBoard. - type SerializableBoard, -} from "./internal/common/serializable.js"; -export { extractTypeFromValue, type Value } from "./internal/common/value.js"; -export { defineNodeType } from "./internal/define/define.js"; -export { type Definition } from "./internal/define/definition.js"; -export { jsonSchemaToPortConfigMap as fromJSONSchema } from "./internal/define/json-schema.js"; -export { type NodeFactoryFromDefinition } from "./internal/define/node-factory.js"; -export { unsafeSchema } from "./internal/define/unsafe-schema.js"; -export { kit } from "./internal/kit.js"; -export { annotate } from "./internal/type-system/annotate.js"; -export { anyOf } from "./internal/type-system/any-of.js"; -export { array } from "./internal/type-system/array.js"; -export { enumeration } from "./internal/type-system/enumeration.js"; -export { intersect } from "./internal/type-system/intersect.js"; -export { jsonSchema } from "./internal/type-system/json-schema.js"; -export { object, optional } from "./internal/type-system/object.js"; -export { string } from "./internal/type-system/string.js"; -export { - toJSONSchema, - type ConvertBreadboardType, - type JsonSerializable, -} from "./internal/type-system/type.js"; -export { unsafeType } from "./internal/type-system/unsafe.js"; diff --git a/packages/build/src/internal/board/board.ts b/packages/build/src/internal/board/board.ts deleted file mode 100644 index 0239694bb23..00000000000 --- a/packages/build/src/internal/board/board.ts +++ /dev/null @@ -1,854 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { NodeDescriberResult, Schema } from "@google-labs/breadboard"; -import type { - GraphMetadata, - NodeMetadata, -} from "@google-labs/breadboard-schema/graph.js"; -import type { JSONSchema4 } from "json-schema"; -import { anyOf, unsafeType, type Value } from "../../index.js"; -import { - InputPort, - isOutputPortReference, - OutputPort, - OutputPortGetter, - type OutputPortReference, - type ValuesOrOutputPorts, -} from "../common/port.js"; -import type { - SerializableBoard, - SerializableInputPort, - SerializableOutputPort, - SerializableOutputPortReference, -} from "../common/serializable.js"; -import { - toJSONSchema, - type BreadboardType, - type JsonSerializable, -} from "../type-system/type.js"; -import { - isSpecialInput, - type GenericSpecialInput, - type Input, - type InputWithDefault, -} from "./input.js"; -import { isOptional } from "./optional.js"; -import { isSpecialOutput, type Output } from "./output.js"; -import type { Loopback } from "./loopback.js"; -import type { Convergence } from "./converge.js"; -import type { - AutoOptional, - Expand, - FlattenUnion, - RemoveReadonly, -} from "../common/type-util.js"; -import type { StarInputs } from "./star-inputs.js"; -import type { KitBinding } from "../kit.js"; - -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - -// TODO(aomarks) Support primary ports in boards. - -/** - * Define a new Breadboard board. - * - * Example usage: - * - * ```ts - * export const recipeMaker = board({ - * inputs: {recipeName}, - * outputs: {recipe: llmRecipeResult} - * }); - * ``` - * - * @param inputs The input ports that should be exposed from nodes in the board - * and under which name. An object that maps from an exposed port name to an - * input port from a node in the board. - * @param output The output ports that should be exposed from nodes in the board - * and under which name. An object that maps from an exposed port name to an - * output port from a node in the board. - * @return A {@link BoardDefinition} which can be serialized for execution or - * distribution, and which can be instantiated for composition into another - * board. - */ -export function board({ - inputs, - outputs, - id, - title, - description, - version, - metadata, - describer, -}: T): BoardDefinition< - Expand>>>, - Expand>>> -> { - const flatInputs = flattenInputs(inputs as any); - const flatOutputs = flattenOutputs(outputs as any); - const newInputs = normalizeBoardInputs(inputs); - const newOutputs = normalizeBoardOutputs(outputs); - const defImpl = new BoardDefinitionImpl( - flatInputs, - flatOutputs, - newInputs, - newOutputs - ); - const definition = Object.assign(defImpl.instantiate.bind(defImpl), { - id, - inputs: flatInputs, - inputsForSerialization: inputs as BoardInputPorts | Array, - outputs: flatOutputs, - outputsForSerialization: outputs as - | BoardOutputPorts - | Array, - title, - description, - version, - metadata, - isBoard: true, - describe: defImpl.describe.bind(defImpl), - describer, - }); - // TODO(aomarks) This is a bit silly, need a small refactor here so that we - // aren't juggling all these objects. The complexity here comes from the fact - // that we want to return a function that also has data attached. - defImpl.definition = definition; - return definition; -} - -/** - * Normalize the 3 allowed forms for board `inputs` to just 1. - */ -function normalizeBoardInputs(inputs: BoardInit["inputs"]): InputNode[] { - if (Array.isArray(inputs)) { - return inputs; - } - if (isInputNode(inputs)) { - return [inputs]; - } - return [inputNode(inputs)]; -} - -/** - * Normalize the 3 allowed forms for board `outputs` to just 1. - */ -function normalizeBoardOutputs(outputs: BoardInit["outputs"]): OutputNode[] { - if (Array.isArray(outputs)) { - return outputs; - } - if (isOutputNode(outputs)) { - return [outputs]; - } - return [outputNode(outputs)]; -} - -function isInputNode(value: unknown): value is InputNode { - return ( - typeof value === "object" && - value !== null && - (value as InputNode)["isInputNode"] === true - ); -} - -function isOutputNode(value: unknown): value is OutputNode { - return ( - typeof value === "object" && - value !== null && - (value as OutputNode)["isOutputNode"] === true - ); -} - -function flattenInputs( - inputs: IPORTS -): FlattenMultiInputs { - if (!Array.isArray(inputs)) { - return inputs as FlattenMultiInputs; - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const ports = {} as any; - for (const inputNode of inputs as Array) { - for (const [name, port] of Object.entries(inputNode)) { - // TODO(aomarks) This is wrong. We're just clobbering. Doesn't matter up - // until we try to invoke a board, which we don't yet support. - ports[name] = port; - } - } - return ports; -} - -function flattenOutputs( - outputs: OPORTS -): FlattenMultiOutputs { - if (!Array.isArray(outputs)) { - return outputs as FlattenMultiOutputs; - } - const ports = {} as FlattenMultiOutputs; - for (const outputNode of outputs as Array) { - for (const [name, port] of Object.entries(outputNode)) { - // TODO(aomarks) This is wrong. We're just clobbering. Doesn't matter up - // until we try to invoke a board, which we don't yet support. - ports[name] = port; - } - } - return ports; -} - -export type FlattenMultiInputs = - I extends Array - ? { - [K in keyof I[number] as K extends "$id" | "$metadata" - ? never - : K]-?: I[number][K] extends - | Input - | InputWithDefault - | undefined - ? undefined extends I[number][K] - ? Input - : Input - : never; - } - : I; - -type FlattenMultiOutputs = - O extends Array - ? { - [K in keyof O[number] as K extends "$id" | "$metadata" - ? never - : K]-?: O[number][K] extends OutputPort | undefined - ? undefined extends O[number][K] - ? OutputPort - : OutputPort - : O[number][K] extends OutputPortReference | undefined - ? undefined extends O[number][K] - ? OutputPortReference - : OutputPortReference - : never; - } - : O; - -export interface BoardParameters< - IPORTS extends BoardInputShape, - OPORTS extends BoardOutputShape, -> { - inputs: IPORTS; - outputs: OPORTS; - id?: string; - title?: string; - description?: string; - version?: string; - metadata?: GraphMetadata; -} - -export type BoardInputShape = - | BoardInputPorts - | Array; - -export type BoardInputPorts = Record< - string, - InputPort | GenericSpecialInput ->; - -export type BoardInputPortsWithUndefined = Record< - string, - | InputPort - | GenericSpecialInput - | string - | undefined - | { title?: string; description?: string } -> & { - $id?: string | undefined; - $metadata?: { title?: string; description?: string; icon?: string }; -}; - -export type BoardOutputShape = - | BoardOutputPorts - | Array; - -export type BoardOutputPorts = Record< - string, - | OutputPortReference - | Output - | Input - | InputWithDefault ->; - -export type BoardOutputPortsWithUndefined = Record< - string, - | OutputPortReference - | Output - | string - | { title?: string; description?: string } - | undefined -> & { - $id?: string | undefined; - $metadata?: { title?: string; description?: string; icon?: string }; -}; - -export type OldBoardDefinition< - IPORTS extends BoardInputPorts, - OPORTS extends BoardOutputPorts, -> = OldBoardInstantiateFunction & { - readonly id?: string; - readonly inputs: IPORTS; - readonly inputsForSerialization: BoardInputPorts | Array; - readonly outputs: OPORTS; - readonly outputsForSerialization: BoardOutputPorts | Array; - readonly title?: string; - readonly description?: string; - readonly version?: string; - readonly metadata?: GraphMetadata; - describe(): Promise; -}; - -// TODO(aomarks) Fix this definition so that it doesn't need . -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type GenericBoardDefinition = OldBoardDefinition; - -type OldBoardInstantiateFunction< - IPORTS extends BoardInputPorts, - OPORTS extends BoardOutputPorts, -> = ( - values: ValuesOrOutputPorts> -) => OldBoardInstance; - -class BoardDefinitionImpl< - IPORTS extends BoardInputPorts, - OPORTS extends BoardOutputPorts, -> { - readonly #inputs: IPORTS; - readonly #outputs: OPORTS; - readonly #newInputs: InputNode[]; - readonly #newOutputs: OutputNode[]; - definition?: OldBoardDefinition; - - constructor( - inputs: IPORTS, - outputs: OPORTS, - newInputs: InputNode[], - newOutputs: OutputNode[] - ) { - this.#inputs = inputs; - this.#outputs = outputs; - this.#newInputs = newInputs; - this.#newOutputs = newOutputs; - } - - instantiate( - values: ValuesOrOutputPorts>, - kitBinding?: KitBinding - ): OldBoardInstance { - return new OldBoardInstance( - this.#inputs, - this.#outputs, - values, - this.definition!, - kitBinding - ); - } - - async describe(): Promise { - return { - inputSchema: this.#describeInputs(), - outputSchema: this.#describeOutputs(), - }; - } - - #describeInputs(): Schema { - const groups: Record = {}; - for (const inputNode of this.#newInputs) { - for (const [name, value] of Object.entries( - // TODO(aomarks) Should not need this cast. - inputNode as object as Record - )) { - if (name === "$id" || name === "$metadata") { - continue; - } - let group = groups[name]; - if (group === undefined) { - group = []; - groups[name] = group; - } - group.push(value); - } - } - - const properties: Record = {}; - const required: string[] = []; - const numInputs = this.#newInputs.length; - for (const [name, values] of Object.entries(groups)) { - const schemasAndRequireds = values.map((value) => describeInput(value)); - const schemas = schemasAndRequireds.map(({ schema }) => schema); - const requireds = schemasAndRequireds - .map(({ required }) => required) - .filter((value) => value); - if (requireds.length === numInputs) { - required.push(name); - } - const uniqueSchemas = new Set( - // TODO(aomarks) This is not an ideal way to compare schemas. - schemas.map((schema) => JSON.stringify(schema)) - ); - if (uniqueSchemas.size === 1) { - properties[name] = schemas[0] as Schema; - } else { - properties[name] = toJSONSchema( - anyOf( - ...(values.map((value) => value.type) as [ - BreadboardType, - BreadboardType, - ]) - ) - ) as Schema; - } - } - - return { - type: "object", - properties, - required, - additionalProperties: false, - }; - } - - #describeOutputs(): Schema { - const groups: Record> = {}; - for (const outputNode of this.#newOutputs) { - for (const [name, value] of Object.entries( - // TODO(aomarks) Should not need this cast. - outputNode as object as Record - )) { - if (name === "$id" || name === "$metadata") { - continue; - } - let group = groups[name]; - if (group === undefined) { - group = []; - groups[name] = group; - } - group.push(value); - } - } - - const properties: Record = {}; - const required: string[] = []; - const numOutputs = this.#newOutputs.length; - for (const [name, values] of Object.entries(groups)) { - const schemasAndRequireds = values.map((value) => - describeOutput( - // TODO(aomarks) Should not need this cast. - value as any - ) - ); - const schemas = schemasAndRequireds.map(({ schema }) => schema); - const requireds = schemasAndRequireds - .map(({ required }) => required) - .filter((value) => value); - if (requireds.length === numOutputs) { - required.push(name); - } - const uniqueSchemas = new Set( - // TODO(aomarks) This is not an ideal way to compare schemas. - schemas.map((schema) => JSON.stringify(schema)) - ); - if (uniqueSchemas.size === 1) { - properties[name] = schemas[0] as Schema; - } else { - properties[name] = toJSONSchema( - anyOf( - ...(schemas.map((schema) => unsafeType(schema)) as object[] as [ - BreadboardType, - BreadboardType, - ]) - ) - ) as Schema; - } - } - - return { - type: "object", - properties, - required, - additionalProperties: false, - }; - } -} - -export class OldBoardInstance< - IPORTS extends BoardInputPorts, - OPORTS extends BoardOutputPorts, -> { - readonly inputs: IPORTS; - readonly outputs: OPORTS; - readonly values: ValuesOrOutputPorts>; - readonly definition: OldBoardDefinition; - readonly __kitBinding?: KitBinding; - - constructor( - inputs: IPORTS, - outputs: OPORTS, - values: ValuesOrOutputPorts>, - definition: OldBoardDefinition, - kitBinding?: KitBinding - ) { - this.inputs = inputs; - this.outputs = this.#tagOutputs(outputs); - this.values = values; - this.definition = definition; - this.__kitBinding = kitBinding; - } - - /** - * Tag all of our outputs with a link back this board instance. This allows us - * to recognize when we are hitting a board boundary during serialization, - * which is important because we need to do special stuff there (e.g. create - * an invoke node). - */ - #tagOutputs(outputs: OPORTS): OPORTS { - return Object.fromEntries( - Object.entries(outputs).map(([name, output]) => [ - name, - { - ...output, - innerPortName: name, - innerBoard: this as object as OldBoardInstance< - BoardInputPorts, - BoardOutputPorts - >, - } satisfies BoardOutput, - ]) - ) as object as OPORTS; - } -} - -export function isBoardInstance( - value: unknown -): value is OldBoardInstance { - // TODO(aomarks) Use a better brand - return ( - (value as Partial>) - .definition !== undefined - ); -} - -export type BoardOutput = ( - | OutputPortReference - | Output - | Input - | InputWithDefault -) & { - innerBoard: OldBoardInstance; - innerPortName: string; -}; - -export function isBoardOutput(value: unknown): value is BoardOutput { - return (value as Partial).innerBoard !== undefined; -} - -type ExtractPortTypes = { - [PORT_NAME in keyof PORTS]: PORTS[PORT_NAME] extends - | InputPort - | Value - ? TYPE - : never; -}; - -export function isBoard(value: unknown): value is GenericBoardDefinition { - return ( - typeof value === "function" && "isBoard" in value && value.isBoard === true - ); -} - -export function describeInput( - input: - | Input - | InputWithDefault - | SerializableInputPort -): { - schema: JSONSchema4; - required: boolean; -} { - const schema = toJSONSchema(input.type); - let isSpecialOptional = false; - if (isSpecialInput(input)) { - if (input.title !== undefined) { - schema.title = input.title; - } - if (input.description !== undefined) { - schema.description = input.description; - } - if (input.default !== undefined) { - schema.default = - typeof input.default === "string" - ? input.default - : // TODO(aomarks) Why is default JSON stringified? The UI currently - // requires it, but seems like it should be real JSON. - JSON.stringify(input.default, null, 2); - } - if (input.examples !== undefined && input.examples.length > 0) { - schema.examples = input.examples.map((example) => - typeof example === "string" - ? example - : // TODO(aomarks) Why is examples JSON stringified? The UI currently - // requires it, but seems like it should be real JSON. - JSON.stringify(example, null, 2) - ); - } - if ("optional" in input && input.optional) { - isSpecialOptional = true; - } - } - const required = schema.default === undefined && !isSpecialOptional; - return { schema, required }; -} - -export function describeOutput( - output: - | SerializableOutputPortReference - | Output - | Input - | InputWithDefault -): { - schema: JSONSchema4; - required: boolean; -} { - let port; - if (isSpecialOutput(output)) { - port = output.port; - } else { - port = output; - } - const required = !isOptional(port); - if (isSerializableOutputPortReference(port)) { - port = port[OutputPortGetter]; - } - // Input | InputWithDefault | SerializableOutputPort | OutputPort<...> - const schema = toJSONSchema(unroll(port as any).type); - if (isSpecialOutput(output)) { - if (output.title !== undefined) { - schema.title = output.title; - } - if (output.description !== undefined) { - schema.description = output.description; - } - } - return { schema, required }; -} - -export function isSerializableOutputPortReference( - value: unknown -): value is SerializableOutputPortReference { - return ( - typeof value === "object" && value !== null && OutputPortGetter in value - ); -} - -export function unroll( - value: - | Input - | InputWithDefault - | Output - | OutputPort - | OutputPortReference - | SerializableOutputPort -): - | Input - | InputWithDefault - | OutputPort - | SerializableOutputPort { - if (isSpecialOutput(value)) { - return unroll(value.port as any); - } - if ("type" in value) { - return value; - } - if (isOutputPortReference(value)) { - return unroll(value[OutputPortGetter]); - } - return value; -} - -// ------------------ -// NEW ZONE -// ------------------ - -export interface BoardInit { - inputs: InputNode | InputNode[] | AnonymousInputNodeShorthand; - outputs: OutputNode | OutputNode[] | AnonymousOutputNodeShorthand; - id?: string; - title?: string; - description?: string; - version?: string; - metadata?: GraphMetadata; - describer?: GenericBoardDefinition; -} - -type AnonymousInputNodeShorthand = Record< - string, - GenericSpecialInput | StarInputs ->; - -type AnonymousOutputNodeShorthand = Record; - -export type BoardDefinition< - I extends Record = any, - O extends Record = any, -> = BoardInstantiateFunction & - SerializableBoard & { describe: () => Promise }; - -export type BoardInstantiateFunction< - I extends Record, - O extends Record, -> = ( - inputs: { - [K in keyof I]: Value; - } & { $id?: string; $metadata?: NodeMetadata } -) => BoardInstance; - -export interface BoardInstance< - I extends Record, - O extends Record, -> { - outputs: Expand>>>; -} - -type FilterSerializable> = { - [K in keyof T]: T[K] extends JsonSerializable | undefined ? T[K] : never; -}; - -type WrapInValues> = { - [K in keyof T]: Value; -}; - -/** - * Board inputs can either be an object (one input node) or an array of objects - * (multiple input nodes). This function returns a union of types in the array - * case. - */ -type SimplifyBoardInitInputs = - T extends InputNode - ? X - : T extends InputNode[] - ? // TODO(amoarks) Recursion shouldn't be needed. - SimplifyBoardInitInputs - : T extends AnonymousInputNodeShorthand - ? ExtractInputTypes - : never; - -/** - * - */ -export type SimplifyBoardInitOutputs = - T extends OutputNode - ? X - : // : T extends Array> - // ? X - T extends Array - ? SimplifyBoardInitOutputs - : T extends AnonymousOutputNodeShorthand - ? ExtractOutputTypes - : never; - -/** - * Pulls out the type parameter for each `Input`, taking care to add `undefined` - * in the case of `InputWithDefault`. This is because when there is a default, - * then it is optional from the caller's perspective. - */ -type ExtractInputTypes< - T extends Record, -> = { - [K in keyof T]: T[K] extends Input - ? X - : T[K] extends InputWithDefault - ? X | undefined - : T[K] extends StarInputs - ? X - : never; -}; - -/** - * Pulls out the type parameter for each `Input`, taking care to add `undefined` - * in the case of `InputWithDefault`. This is because when there is a default, - * then it is optional from the caller's perspective. - */ -type ExtractOutputTypes> = - { - // prettier-ignore - [K in keyof T]: - T[K] extends Input ? X : - T[K] extends InputWithDefault ? X | undefined : - T[K] extends Output ? X : - T[K] extends OutputPort ? X : - T[K] extends OutputPortReference ? X : - T[K] extends Loopback ? X : - T[K] extends Convergence ? X : - T[K] extends Value ? X : - never - // prettier-ignore-end - }; - -export function inputNode< - T extends Record, ->( - inputs: T, - metadata?: NodeMetadata & { id?: string } -): InputNode>> { - const result: Record = { ...inputs }; - if (metadata) { - if (metadata.id) { - result.$id = metadata.id; - metadata = { ...metadata }; - delete metadata["id"]; - } - result.$metadata = metadata; - } - return result as unknown as InputNode>; -} - -export interface InputNode< - T extends Record = Record< - string, - JsonSerializable | undefined - >, -> { - // TODO(aomarks) Better branding - isInputNode: true; -} - -export function outputNode< - T extends Record, ->( - outputs: T, - metadata?: NodeMetadata & { id?: string } & { bubble?: boolean } -): OutputNode>> { - const result: Record = { ...outputs }; - if (metadata) { - if (metadata.id) { - result.$id = metadata.id; - metadata = { ...metadata }; - delete metadata["id"]; - } - if (metadata.bubble) { - result.$bubble = metadata.bubble; - metadata = { ...metadata }; - delete metadata["bubble"]; - } - result.$metadata = metadata; - } - return result as unknown as OutputNode>; -} - -export interface OutputNode< - T extends Record = Record< - string, - JsonSerializable | undefined - >, -> { - // TODO(aomarks) Better branding - isOutputNode: true; -} diff --git a/packages/build/src/internal/board/constant.ts b/packages/build/src/internal/board/constant.ts deleted file mode 100644 index 89b459ea074..00000000000 --- a/packages/build/src/internal/board/constant.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { brand, isBranded } from "../common/brand.js"; -import { type OutputPortReference } from "../common/port.js"; -import type { JsonSerializable } from "../type-system/type.js"; -import type { Input, InputWithDefault } from "./input.js"; - -// TODO(aomarks) Possible other names: `sticky`, `persistent`, `retained`. -// `memoized` was also used previously, but that makes me think of caching which -// is performance-oriented, whereas this actually affects functional control -// flow). We're using `constant` for now though because it's nice to be be -// consistent with BGL. - -/** - * Cause a value to be retained indefinitely during Breadboard execution, - * instead of the default behavior where it is consumed. - * - * In BGL terms, wrapping a Breadboard output port with `constant` means that - * any edges connected from that wrapped version of the port will have the - * `constant` bit set on its BGL `edges` object. - */ -export function constant< - T extends - | OutputPortReference - | Input - | InputWithDefault, ->(output: T): T { - return { - [brand]: "Constant", - ...output, - [ConstantVersionOf]: output, - }; -} - -export const ConstantVersionOf = Symbol(); - -interface Constant { - readonly [brand]: "Constant"; - [ConstantVersionOf]: - | OutputPortReference - | Input - | InputWithDefault; -} - -export function isConstant(value: unknown): value is Constant { - return isBranded(value, "Constant"); -} diff --git a/packages/build/src/internal/board/converge.ts b/packages/build/src/internal/board/converge.ts deleted file mode 100644 index b943ef72def..00000000000 --- a/packages/build/src/internal/board/converge.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { brand, isBranded } from "../common/brand.js"; -import type { OutputPortReference } from "../common/port.js"; -import type { BroadenBasicType } from "../common/type-util.js"; -import type { JsonSerializable } from "../type-system/type.js"; -import type { Input, InputWithDefault } from "./input.js"; -import type { Loopback } from "./loopback.js"; - -type Convergable = - | T - | OutputPortReference - | Input - | InputWithDefault - | Loopback; - -export function converge< - A extends Convergable, - B extends Convergable, - C extends Array>, ->( - first: A, - second: B, - ...rest: C -): Convergence> { - return { - [brand]: "Convergence", - ports: [first, second, ...rest] as Array< - Convergable> - >, - }; -} - -type ExtractType> = - T extends Convergable - ? X extends string | number | boolean - ? BroadenBasicType - : X - : never; - -export interface Convergence { - readonly [brand]: "Convergence"; - ports: Array>; -} - -export function isConvergence(value: unknown): value is Convergence { - return isBranded(value, "Convergence"); -} diff --git a/packages/build/src/internal/board/input.ts b/packages/build/src/internal/board/input.ts deleted file mode 100644 index 20760c021b3..00000000000 --- a/packages/build/src/internal/board/input.ts +++ /dev/null @@ -1,276 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -import type { BroadenBasicType, Defined } from "../common/type-util.js"; -import { defineNodeType } from "../define/define.js"; -import { jsonSchema } from "../type-system/json-schema.js"; -import type { - BreadboardType, - ConvertBreadboardType, - JsonSerializable, -} from "../type-system/type.js"; - -type Optionalize< - T extends Record, - X extends JsonSerializable | undefined, -> = T["optional"] extends true ? X | undefined : X; - -// no parameters -export function input(): Input; - -// type and default -export function input>( - params: T & { type: Defined; default: Defined } & CheckParams -): InputWithDefault< - T["type"] extends BreadboardType - ? ConvertBreadboardType - : JsonSerializable ->; - -// just type -export function input>( - params: T & { type: Defined } & CheckParams -): Input< - Optionalize< - T, - T["type"] extends BreadboardType - ? ConvertBreadboardType - : JsonSerializable - > ->; - -// just default -export function input>( - params: T & - LooseParams & { default: Defined; type?: undefined } & CheckParams -): InputWithDefault< - T["default"] extends string | number | boolean - ? BroadenBasicType - : JsonSerializable ->; - -// string by default (required) -export function input(params: { - $id?: string; - description?: string; - title?: string; - type?: undefined; - default?: undefined; - examples?: undefined; - optional?: undefined; -}): Input; - -// string by default (optional) -export function input(params: { - $id?: string; - description?: string; - title?: string; - type?: undefined; - default?: undefined; - examples?: undefined; - optional: true; -}): Input; - -// just examples -export function input>( - params: T & { examples: Defined } & CheckParams -): Input< - Optionalize< - T, - T["examples"] extends string[] | number[] | boolean[] - ? BroadenBasicType - : JsonSerializable - > ->; - -/** - * Declare an input for a board. - */ -export function input( - params?: LooseParams -): Input | InputWithDefault { - let type: BreadboardType; - if (params?.type !== undefined) { - type = params.type; - } else if ( - params?.default !== undefined || - params?.examples?.[0] !== undefined - ) { - switch (typeof (params.default ?? params.examples?.[0])) { - case "string": { - type = "string"; - break; - } - case "number": { - type = "number"; - break; - } - case "boolean": { - type = "boolean"; - break; - } - default: { - throw new Error( - `Unknown default type: ${JSON.stringify(params.default)}` - ); - } - } - } else { - type = "string"; - } - return { - __SpecialInputBrand: true, - id: params?.$id, - type, - title: params?.title, - description: params?.description, - default: params?.default, - examples: params?.examples, - optional: params?.optional, - } satisfies - | Omit, "__type"> - | InputWithDefault as - | Input - | InputWithDefault; -} - -interface LooseParams { - $id?: string; - type?: BreadboardType; - title?: string; - description?: string; - default?: JsonSerializable; - examples?: JsonSerializable[]; - optional?: true; -} - -export interface Input { - readonly __SpecialInputBrand: true; - readonly __type: T; - readonly id?: string; - readonly type: BreadboardType; - readonly title?: string; - readonly description?: string; - readonly default: undefined; - readonly examples?: T[]; - readonly optional?: boolean; -} - -export interface InputWithDefault { - readonly __SpecialInputBrand: true; - readonly id?: string; - readonly title?: string; - readonly type: BreadboardType; - readonly description?: string; - readonly default: T; - readonly examples?: T[]; -} - -export type GenericSpecialInput = - | Input - | InputWithDefault; - -type CheckParams = (T["type"] extends Defined - ? { - $id?: string; - type: BreadboardType; - title?: string; - default?: T["type"] extends BreadboardType - ? ConvertBreadboardType - : JsonSerializable; - examples?: Array< - T["type"] extends BreadboardType - ? ConvertBreadboardType - : JsonSerializable - >; - description?: string; - optional?: T["default"] extends Defined ? never : true; - } - : T["default"] extends Defined - ? { - $id?: string; - type?: never; - title?: string; - default: string | number | boolean; - examples?: Array; - description?: string; - optional?: never; - } - : T["examples"] extends Defined - ? { - $id?: string; - type?: never; - title?: string; - default?: never; - examples?: string[] | number[] | boolean[]; - description?: string; - optional?: true; - } - : never) & { - [K in keyof T]: K extends - | "$id" - | "type" - | "title" - | "default" - | "examples" - | "description" - | "optional" - ? unknown - : never; -}; - -export function isSpecialInput(value: unknown): value is GenericSpecialInput { - return ( - typeof value === "object" && - value !== null && - "__SpecialInputBrand" in value - ); -} - -/** - * Usually, inputs are created with the {@link input} and {@link inputNode} - * functions, which abstract Breadboard inputs to make them more powerful and - * ergonomic while using the Build API. - * - * This `rawInput` function, in contrast, creates an input component that - * behaves like a totally normal component that happens to have the type - * "input". - * - * This gives you full freedom to wire an input node up in arbitrary ways in a - * board, for example if you need the schema to be provided by the output of - * another component, rather than being statically defined. - * - * Note that you will need to use {@link unsafeOutput} to access any output - * ports of this component. - */ -export const rawInput = defineNodeType({ - name: "input", - inputs: { - schema: { - type: jsonSchema, - }, - }, - outputs: { - "*": { - type: "unknown", - }, - }, - describe: () => { - // TODO(aomarks) Replace this with Breadboard interfaces when they exist. - // - // These definitions are stubs. They exist only so that we have a way to - // declare input and output nodes using the Build API. Every runtime is - // responsible for providing its own real implementation of "input" and - // "output". So, we throw here and below in case this implementations - // somehow make their way into a runtime environment. - throw new Error("Unexpected call to stub input describe()"); - }, - invoke: () => { - throw new Error("Unexpected call to stub input invoke()"); - }, -}); diff --git a/packages/build/src/internal/board/loopback.ts b/packages/build/src/internal/board/loopback.ts deleted file mode 100644 index 5730a0313d2..00000000000 --- a/packages/build/src/internal/board/loopback.ts +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { brand, isBranded } from "../common/brand.js"; -import type { OutputPortReference } from "../common/port.js"; -import type { - BreadboardType, - ConvertBreadboardType, - JsonSerializable, -} from "../type-system/type.js"; - -export function loopback(): Loopback; - -export function loopback( - params: LoopbackParams -): Loopback>; - -/** - * Create a new Breadboard loopback. - * - * Loopbacks can be used in place of real output ports for situations where it - * is not yet possible to provide an actual output port because of a cycle in - * the Breadboard program graph. - * - * IMPORTANT: The `resolve` method must be called on loopbacks before the - * `board` function is called. - */ -export function loopback( - params?: LoopbackParams -): Loopback { - return new Loopback(params?.type ?? "string"); -} - -interface LoopbackParams { - type: T; -} - -export type { Loopback }; -/** - * Loopbacks can be used in place of real output ports for situations where it - * is not yet possible to provide an actual output port, most notably because of - * a cycle. - * - * IMPORTANT: The `resolve` method must be called on loopbacks before the - * `board` function is called. - */ -class Loopback { - readonly [brand] = "Loopback"; - readonly type: BreadboardType; - #value?: OutputPortReference; - - constructor(type: BreadboardType) { - this.type = type; - } - - /** - * Set the value of this Loopback. Throws if this Loopback has already - * been resolved. - */ - resolve(value: OutputPortReference): void { - if (this.#value !== undefined) { - throw new Error("Loopback has already been resolved"); - } - this.#value = value; - } - - /** - * Get the resolved value, or `undefined` if it has not yet been resolved. - */ - get value(): OutputPortReference | undefined { - return this.#value; - } -} - -/** - * Test whether the given object is a Breadboard {@link Loopback}. - */ -export function isLoopback(value: unknown): value is Loopback { - return isBranded(value, "Loopback"); -} diff --git a/packages/build/src/internal/board/optional.ts b/packages/build/src/internal/board/optional.ts deleted file mode 100644 index b4aa49c2b0e..00000000000 --- a/packages/build/src/internal/board/optional.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { brand, isBranded } from "../common/brand.js"; -import { type OutputPortReference } from "../common/port.js"; -import type { JsonSerializable } from "../type-system/type.js"; -import type { Input, InputWithDefault } from "./input.js"; - -/** - * Make it so when there is no value on this port, it will still be possible to - * invoke connected nodes. - * - * In BGL terms, wrapping a Breadboard output port with `optionalEdge` means - * that any edges connected from that wrapped version of the port will have the - * `optional` bit set on its BGL `edges` object. - */ -export function optionalEdge< - T extends - | OutputPortReference - | Input - | InputWithDefault, ->(output: T): T { - return { - [brand]: "Optional", - ...output, - [OptionalVersionOf]: output, - }; -} - -export const OptionalVersionOf = Symbol(); - -interface Optional { - [OptionalVersionOf]: - | OutputPortReference - | Input - | InputWithDefault; -} - -export function isOptional(value: unknown): value is Optional { - return isBranded(value, "Optional"); -} diff --git a/packages/build/src/internal/board/output.ts b/packages/build/src/internal/board/output.ts deleted file mode 100644 index bca513f2d13..00000000000 --- a/packages/build/src/internal/board/output.ts +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { brand, isBranded } from "../common/brand.js"; -import type { Value } from "../common/value.js"; -import type { JsonSerializable } from "../type-system/type.js"; - -export function output( - port: Value, - { - id, - title, - description, - deprecated, - }: { - id?: string; - title?: string; - description?: string; - deprecated?: boolean; - } = {} -): Output { - return { - [brand]: "Output", - id, - title, - description, - port, - deprecated, - }; -} - -export interface Output< - T extends JsonSerializable | undefined = JsonSerializable | undefined, -> { - readonly [brand]: "Output"; - readonly id?: string; - readonly title?: string; - readonly description?: string; - readonly port: Value; - readonly deprecated?: boolean; -} - -export function isSpecialOutput(value: unknown): value is Output { - return isBranded(value, "Output"); -} diff --git a/packages/build/src/internal/board/serialize.ts b/packages/build/src/internal/board/serialize.ts deleted file mode 100644 index 70916d42312..00000000000 --- a/packages/build/src/internal/board/serialize.ts +++ /dev/null @@ -1,656 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/* eslint-disable @typescript-eslint/no-explicit-any */ - -// TODO(aomarks) Switch import to schema package -import type { - BehaviorSchema, - GraphDescriptor, - NodeDescriptor, - NodeValue, - Schema, -} from "@google-labs/breadboard"; -import type { JSONSchema4 } from "json-schema"; -import { DefaultValue, OutputPortGetter } from "../common/port.js"; -import type { - SerializableBoard, - SerializableInputPort, - SerializableNode, -} from "../common/serializable.js"; -import { type JsonSerializable } from "../type-system/type.js"; -import { - OldBoardInstance, - describeInput, - describeOutput, - isBoard, - isBoardInstance, - isBoardOutput, - isSerializableOutputPortReference, - type BoardInputPorts, - type BoardOutputPorts, - type GenericBoardDefinition, -} from "./board.js"; -import { ConstantVersionOf, isConstant } from "./constant.js"; -import { isConvergence } from "./converge.js"; -import { - isSpecialInput, - type GenericSpecialInput, - type Input, - type InputWithDefault, -} from "./input.js"; -import { isLoopback } from "./loopback.js"; -import { OptionalVersionOf, isOptional } from "./optional.js"; -import { isSpecialOutput } from "./output.js"; -import { isStarInputs, type StarInputs } from "./star-inputs.js"; -import type { NodeMetadata } from "@google-labs/breadboard-schema/graph.js"; - -/** - * Serialize a Breadboard board to Breadboard Graph Language (BGL) so that it - * can be executed. - */ -export function serialize(board: SerializableBoard): GraphDescriptor { - const nodes = new Map(); - const edges: Edge[] = []; - const graphs = new Map(); - const errors: string[] = []; - const typeCounts = new Map(); - let nextEmbeddedGraphId = 0; - - // Prepare our main input and output nodes. They represent the overall - // signature of the board. - const outputNodes = new Map(); - - // Analyze inputs and remember some things about them that we'll need when we - // traverse the outputs. - const inputNodes = new Map(); - const inputObjectsToInputNodeInfo = new Map< - | Input - | InputWithDefault - | StarInputs - | SerializableInputPort, - { nodeId: string; portName: string } - >(); - - const unconnectedInputs = new Set< - | Input - | InputWithDefault - | StarInputs - | SerializableInputPort - >(); - - const inputsArray = ( - Array.isArray(board.inputsForSerialization) - ? board.inputsForSerialization - : [board.inputsForSerialization] - ) as Array< - Record< - string, - | SerializableInputPort - | Input - | InputWithDefault - > - >; - const magicInputResolutions = new Map< - GenericSpecialInput, - { nodeId: string; portName: string } - >(); - for (const inputs of inputsArray) { - const sortedBoardInputs = Object.entries(inputs).sort( - // Sort so that mainInputSchema will also be sorted. - ([nameA], [nameB]) => nameA.localeCompare(nameB) - ); - let iterationInputId: string | undefined = undefined; - const autoId = () => { - if (iterationInputId === undefined) { - iterationInputId = nextIdForType("input"); - } - return iterationInputId; - }; - for (const [mainInputName, input] of sortedBoardInputs) { - if (mainInputName === "$id" || mainInputName === "$metadata") { - continue; - } - // if (inputObjectsToInputNodeInfo.has(input)) { - // errors.push( - // `The same input was used as both ` + - // `${inputObjectsToInputNodeInfo.get(input)!.portName} and ${mainInputName}.` - // ); - // } - const inputNodeId = - (inputs.$id as string | undefined) ?? - (isSpecialInput(input) ? input.id : undefined) ?? - autoId(); - - inputObjectsToInputNodeInfo.set(input, { - nodeId: inputNodeId, - portName: mainInputName, - }); - unconnectedInputs.add(input); - const { schema, required } = describeInput(input); - let inputNode = inputNodes.get(inputNodeId); - if (inputNode === undefined) { - inputNode = { - id: inputNodeId, - type: "input", - configuration: { - schema: { - type: "object", - properties: {}, - required: [], - // TODO(aomarks) Disallow extra properties? - }, - }, - }; - const metadata = inputs.$metadata as { - title?: string; - description?: string; - }; - if (metadata !== undefined) { - inputNode.metadata = metadata; - } - inputNodes.set(inputNodeId, inputNode); - } - const normalizedSchema = sortKeys(schema, [ - "type", - "behavior", - "title", - "description", - "default", - "examples", - "anyOf", - "properties", - "items", - "required", - "additionalProperties", - ]); - if (mainInputName === "*") { - inputNode.configuration.schema.additionalProperties = normalizedSchema; - } else { - inputNode.configuration.schema.properties[mainInputName] = - normalizedSchema; - if (required) { - inputNode.configuration.schema.required.push(mainInputName); - } - } - if (isSpecialInput(input)) { - magicInputResolutions.set(input, { - nodeId: inputNodeId, - portName: mainInputName, - }); - } - } - } - - const outputsArray = Array.isArray(board.outputsForSerialization) - ? board.outputsForSerialization - : [board.outputsForSerialization]; - for (const outputs of outputsArray) { - // Recursively traverse the graph starting from outputs. - const sortedBoardOutputs = Object.entries(outputs).sort( - // Sort so that mainOutputSchema will also be sorted. - ([nameA], [nameB]) => nameA.localeCompare(nameB) - ); - let iterationOutputId: string | undefined = undefined; - const autoId = () => { - if (iterationOutputId === undefined) { - iterationOutputId = nextIdForType("output"); - } - return iterationOutputId; - }; - for (const [name, output] of sortedBoardOutputs) { - if (name.startsWith("$") && name !== "$error") { - continue; - } - - let nested = isBoardOutput(output) ? output : undefined; - let port; - let outputNodeId; - let deprecated = false; - const portMetadata: { title?: string; description?: string } = {}; - if (isSpecialOutput(output)) { - port = output.port; - if (nested === undefined) { - outputNodeId = output.id; - if (output.title) { - portMetadata.title = output.title; - } - if (output.description) { - portMetadata.description = output.description; - } - } - deprecated = output.deprecated ?? false; - } else { - port = output; - } - - nested = nested ?? (isBoardOutput(port) ? port : undefined); - - if (isSerializableOutputPortReference(port)) { - port = port[OutputPortGetter]; - } - // TODO(aomarks) Remove cast. - outputNodeId ??= outputs.$id as string | undefined; - outputNodeId ??= autoId(); - - let outputNode = outputNodes.get(outputNodeId); - if (outputNode === undefined) { - outputNode = { - id: outputNodeId, - type: "output", - configuration: { - schema: { - type: "object", - properties: {}, - required: [], - // TODO(aomarks) Disallow extra properties? - }, - }, - }; - const nodeMetadata = outputs.$metadata as { - title?: string; - description?: string; - }; - if (nodeMetadata !== undefined) { - outputNode.metadata = nodeMetadata; - } - if (outputs.$bubble) { - addBehavior(outputNode.configuration.schema, "bubble"); - } - - outputNodes.set(outputNodeId, outputNode); - } - const { schema, required } = describeOutput(output); - outputNode.configuration.schema.properties[name] = schema; - if (deprecated) { - addBehavior(schema, "deprecated"); - } - if (required) { - outputNode.configuration.schema.required.push(name); - } - if (nested !== undefined) { - const { innerBoard, innerPortName } = nested; - addEdge( - visitNodeAndReturnItsId(innerBoard), - innerPortName, - outputNodeId, - name, - isConstant(output), - !required - ); - } else if (isSpecialInput(port)) { - unconnectedInputs.delete(port); - const resolution = magicInputResolutions.get(port); - if (resolution !== undefined) { - addEdge( - resolution.nodeId, - resolution.portName, - outputNodeId, - name, - isConstant(output), - !required - ); - } - } else if ("node" in (port as any)) { - addEdge( - visitNodeAndReturnItsId((port as any).node), - (port as any).name, - outputNodeId, - name, - isConstant(output), - !required - ); - } - } - } - - if (unconnectedInputs.size > 0) { - for (const input of unconnectedInputs.values()) { - errors.push( - `Board input "${inputObjectsToInputNodeInfo.get(input)!.portName}" ` + - `is not reachable from any of its outputs.` - ); - } - } - - if (board.describer) { - const describerId = embedBoardAndReturnItsId(board.describer); - board.metadata ??= {}; - board.metadata.describer = `#${describerId}`; - } - - if (errors.length > 0) { - // TODO(aomarks) Refactor this to a Result<> return, because these errors are - // expected as part of the normal course of operation. - throw new Error( - `Error serializing board:\n\n${errors.sort().join("\n\n")}` - ); - } - - const bgl: GraphDescriptor = { - ...(board.title ? { title: board.title } : {}), - ...(board.description ? { description: board.description } : {}), - ...(board.version ? { version: board.version } : {}), - ...(board.metadata ? { metadata: board.metadata } : {}), - // Sort the nodes and edges for deterministic BGL output. - edges: edges.sort((a, b) => { - if (a.from != b.from) { - return a.from.localeCompare(b.from); - } - if (a.to != b.to) { - return a.to.localeCompare(b.to); - } - if (a.out != b.out) { - return a.out.localeCompare(b.out); - } - if (a.in != b.in) { - return a.in.localeCompare(b.in); - } - return 0; - }), - nodes: [ - ...[...inputNodes.values()].sort((a, b) => a.id.localeCompare(b.id)), - ...[...outputNodes.values()].sort((a, b) => a.id.localeCompare(b.id)), - ...[...nodes.values()].sort((a, b) => a.id.localeCompare(b.id)), - ], - }; - if (graphs.size > 0) { - bgl.graphs = Object.fromEntries([...graphs]); - } - return bgl; - - function visitNodeAndReturnItsId( - node: SerializableNode | OldBoardInstance - ): string { - let descriptor = nodes.get(node); - if (descriptor !== undefined) { - return descriptor.id; - } - let type, metadata, thisNodeId; - let isBoardInstanceBoundToKit = false; - if (isBoardInstance(node)) { - const kitBinding = node.__kitBinding; - if (kitBinding) { - isBoardInstanceBoundToKit = true; - type = kitBinding.id; - metadata = node.values["$metadata"] as NodeMetadata | undefined; - thisNodeId = - (node.values["$id"] as string | undefined) ?? nextIdForType(type); - } else { - type = "invoke"; - metadata = node.values["$metadata"] as NodeMetadata | undefined; - thisNodeId = - (node.values["$id"] as string | undefined) ?? nextIdForType("invoke"); - } - } else { - const cast = node as SerializableNode; - type = cast.type; - metadata = cast.metadata; - thisNodeId = cast.id ?? nextIdForType(type); - } - - const configuration: Record = {}; - descriptor = { id: thisNodeId, type, configuration }; - - const { title, description, logLevel } = metadata ?? {}; - if (title || description) { - descriptor.metadata = {}; - if (title) { - descriptor.metadata.title = title; - } - if (logLevel) { - descriptor.metadata.logLevel = logLevel; - } - if (description) { - descriptor.metadata.description = description; - } - } - // Note it's important we add the node to the nodes map before we next - // recurse, or else we can get stuck in a loop. - nodes.set(node, descriptor); - - const configurationEntries: Array<[string, NodeValue]> = []; - if (isBoardInstance(node) && !isBoardInstanceBoundToKit) { - configurationEntries.push([ - "$board", - `#${embedBoardAndReturnItsId(node.definition)}`, - ]); - } - for (const [portName, inputPort] of Object.entries( - isBoardInstance(node) ? node.values : node.inputs - )) { - if (portName === "$id" || portName === "$metadata") { - continue; - } - unconnectedInputs.delete(inputPort); - const values = isConvergence(inputPort.value) - ? inputPort.value.ports - : inputPort.value - ? [inputPort.value] - : [inputPort]; - for (let value of values) { - let wasConstant = false; - if (isConstant(value)) { - // TODO(aomarks) The way constant works is kind of hacky. - value = value[ConstantVersionOf]; - wasConstant = true; - } - - let wasOptional = false; - if (isOptional(value)) { - // TODO(aomarks) The way optional works is kind of hacky. - value = value[OptionalVersionOf]; - wasOptional = true; - } - - if (isBoardOutput(value)) { - addEdge( - visitNodeAndReturnItsId(value.innerBoard), - value.innerPortName, - thisNodeId, - portName, - wasConstant, - wasOptional - ); - continue; - } - - if (isLoopback(value)) { - value = value.value; - if (value === undefined) { - // TODO(aomarks) Provide more information about which loopback it - // is. - throw new Error("Loopback was never resolved"); - } - } - - if (isSpecialInput(value)) { - unconnectedInputs.delete(value); - const inputNodeInfo = inputObjectsToInputNodeInfo.get(value); - if (inputNodeInfo !== undefined) { - addEdge( - inputNodeInfo.nodeId, - inputNodeInfo.portName, - thisNodeId, - portName, - wasConstant, - wasOptional - ); - } else { - // TODO(aomarks) Does it actually make sense in some cases to wire up - // an input, but not make it part of the board's interface? In that - // case it would seem to mean that it's *only* possible for that value - // to be provided externally (e.g. by asking the user at runtime), not - // through a value wired into the board. - errors.push( - `${thisNodeId}:${portName} was wired to an input, ` + - `but that input was not provided to the board inputs.` - ); - } - } else if (isStarInputs(value)) { - unconnectedInputs.delete(value); - const inputNodeInfo = inputObjectsToInputNodeInfo.get(value); - if (inputNodeInfo !== undefined) { - addEdge( - inputNodeInfo.nodeId, - "*", - thisNodeId, - // TODO(aomarks) Kind of weird. If the input port is also "*", - // then the runtime seems to just stop. Only "" works. However, if - // you paste some BGL with "" into the Visual Editor it errors, - // and the docs say that star ports "can only be wired to other - // star ports". - "", - wasConstant, - wasOptional - ); - } else { - errors.push( - `${thisNodeId}:${portName} was wired to an input, ` + - `but that input was not provided to the board inputs.` - ); - } - } else if (isSerializableOutputPortReference(value)) { - const wiredOutputPort = value[OutputPortGetter]; - addEdge( - visitNodeAndReturnItsId(wiredOutputPort.node), - wiredOutputPort.name, - thisNodeId, - portName, - wasConstant, - wasOptional - ); - } else if (value === DefaultValue) { - // Omit the value. - } else if (isConvergence(value)) { - throw new Error( - `Internal error: value was convergent for a ${inputPort.node.type}:${inputPort.name} port. Nesting convergent is not supported.` - ); - } else if (value === undefined) { - // TODO(aomarks) Why is this possible in the type system? An inport port - // value can never actually be undefined, right? - throw new Error( - `Internal error: value was undefined for a ${inputPort.node?.type}:${inputPort.name} port.` - ); - } else if (typeof value === "symbol") { - // TODO(aomarks) Why is this possible in the type system? This should - // also not be possible. - throw new Error( - `Internal error: value was a symbol (${String(value)}) for a ${inputPort.node.type}:${inputPort.name} port.` - ); - } else if (isBoard(value)) { - configurationEntries.push([ - portName, - { - kind: "board", - path: `#${embedBoardAndReturnItsId(value)}`, - }, - ]); - } else if ( - typeof value === "object" && - value.constructor !== Object && - "value" in value - ) { - configurationEntries.push([portName, value.value]); - } else { - configurationEntries.push([ - portName, - value satisfies JsonSerializable as NodeValue, - ]); - } - } - } - - // Sort the configuration object for deterministic BGL output. - configurationEntries.sort(([aKey], [bKey]) => aKey.localeCompare(bKey)); - for (const [key, val] of Object.values(configurationEntries)) { - configuration[key] = val; - } - - return thisNodeId; - } - - function addEdge( - from: string, - fromPort: string, - to: string, - toPort: string, - constant: boolean, - optional: boolean - ) { - const edge: Edge = { from, to, out: fromPort, in: toPort }; - if (constant) { - edge.constant = true; - } - if (optional) { - edge.optional = true; - } - edges.push(edge); - } - - function nextIdForType(type: string): string { - const count = typeCounts.get(type) ?? 0; - typeCounts.set(type, count + 1); - return `${type}-${count}`; - } - - function embedBoardAndReturnItsId(board: GenericBoardDefinition): string { - const id = `subgraph-${nextEmbeddedGraphId}`; - nextEmbeddedGraphId++; - graphs.set(id, serialize(board)); - return id; - } -} - -// Note this is a little stricter than the standard Edge type. -type Edge = { - from: string; - out: string; - to: string; - in: string; - constant?: true; - optional?: true; -}; - -type InputOrOutputNodeDescriptor = NodeDescriptor & { - configuration: { - schema: JSONSchema4 & { - properties: Record; - required: string[]; - }; - }; -}; - -function sortKeys>( - obj: T, - fieldOrder: string[] -): T { - return Object.fromEntries( - Object.entries(obj).sort(([nameA], [nameB]) => { - const indexA = fieldOrder.indexOf(nameA); - const indexB = fieldOrder.indexOf(nameB); - if (indexA !== indexB) { - return ( - (indexA === -1 ? Number.MAX_VALUE : indexA) - - (indexB === -1 ? Number.MAX_VALUE : indexB) - ); - } - return nameA.localeCompare(nameB); - }) - ) as T; -} - -function addBehavior( - schema: Schema | JSONSchema4, - behavior: BehaviorSchema -): void { - if (schema.behavior === undefined) { - schema.behavior = [behavior]; - } else if (!schema.behavior.includes(behavior)) { - schema.behavior.push(behavior); - schema.behavior.sort(); - } -} diff --git a/packages/build/src/internal/board/star-inputs.ts b/packages/build/src/internal/board/star-inputs.ts deleted file mode 100644 index 0c4bd775c23..00000000000 --- a/packages/build/src/internal/board/star-inputs.ts +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { brand, isBranded } from "../common/brand.js"; -import type { - BreadboardType, - ConvertBreadboardType, - JsonSerializable, -} from "../type-system/type.js"; - -/** - * Initialization parameters for {@link starInputs}. - */ -export interface StarInputsInit { - type: T; -} - -/** - * Get a handle to the "star ports" from a board's input components. - */ -export function starInputs({ - type, -}: StarInputsInit): StarInputs> { - return new StarInputs(type); -} - -export type { StarInputs }; - -class StarInputs< - T extends JsonSerializable | undefined = JsonSerializable | undefined, -> { - readonly [brand] = "StarInputs"; - readonly type: BreadboardType; - - constructor(type: BreadboardType) { - this.type = type; - } -} - -/** - * Test whether the given object is a Breadboard {@link StarInputs}. - */ -export function isStarInputs(value: unknown): value is StarInputs { - return isBranded(value, "StarInputs"); -} diff --git a/packages/build/src/internal/board/unsafe-cast.ts b/packages/build/src/internal/board/unsafe-cast.ts deleted file mode 100644 index 397530b5b72..00000000000 --- a/packages/build/src/internal/board/unsafe-cast.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - OutputPort, - OutputPortGetter, - type OutputPortReference, -} from "../common/port.js"; -import type { - BreadboardType, - ConvertBreadboardType, - JsonSerializable, -} from "../type-system/type.js"; - -export function unsafeCast< - O extends JsonSerializable, - B extends BreadboardType, ->( - output: OutputPortReference, - type: B -): OutputPortReference> { - const actualOutput = output[OutputPortGetter]; - return new OutputPort(type, actualOutput.name, actualOutput.node); -} diff --git a/packages/build/src/internal/common/brand.ts b/packages/build/src/internal/common/brand.ts deleted file mode 100644 index abc20f0e3ac..00000000000 --- a/packages/build/src/internal/common/brand.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * A global symbol used for annotating the types of objects in the Breadboard - * Build package. - * - * Compared to `instanceof` checks, branding with a global symbol allows type - * recognition even across two versions of the same package (which is not - * uncommon in the npm world). - */ -export const brand = Symbol.for("breadboard-brand"); - -/** - * Check whether an object has the given branding. - * @see {@link brand}. - */ -export function isBranded(value: unknown, branding: string): boolean { - return ( - typeof value === "object" && - value !== null && - (value as { [brand]?: string })[brand] === branding - ); -} diff --git a/packages/build/src/internal/common/compatibility.ts b/packages/build/src/internal/common/compatibility.ts deleted file mode 100644 index e57ad5ddc23..00000000000 --- a/packages/build/src/internal/common/compatibility.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - NodeDescriberFunction, - NodeHandlerFunction, -} from "@google-labs/breadboard"; - -/** - * A more tightly constrained version of {@link NodeHandler}. - * - * TODO(aomarks) Give stronger types to invoke and describe, parameterized by - * the node definition they belong to. - */ -export interface StrictNodeHandler { - readonly invoke: NodeHandlerFunction; - readonly describe: NodeDescriberFunction; -} diff --git a/packages/build/src/internal/common/error.ts b/packages/build/src/internal/common/error.ts deleted file mode 100644 index bfd448f339c..00000000000 --- a/packages/build/src/internal/common/error.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { anyOf } from "../type-system/any-of.js"; -import { object } from "../type-system/object.js"; -import type { ConvertBreadboardType } from "../type-system/type.js"; - -export const breadboardErrorType = anyOf( - object({ message: "string" }), - object({ kind: "string", error: object({ message: "string" }) }) -); - -export type BreadboardError = ConvertBreadboardType; - -export function normalizeBreadboardError(value: unknown): BreadboardError { - if (value !== null && typeof value === "object") { - if ("kind" in value && value.kind === "error") { - return value as BreadboardError; - } - if ("message" in value) { - return { kind: "error", error: value } as BreadboardError; - } - } - const message = typeof value === "string" ? value : JSON.stringify(value); - return { kind: "error", error: { message } }; -} diff --git a/packages/build/src/internal/common/port.ts b/packages/build/src/internal/common/port.ts deleted file mode 100644 index 4a3970d1102..00000000000 --- a/packages/build/src/internal/common/port.ts +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { Input, InputWithDefault } from "../board/input.js"; -import type { Loopback } from "../board/loopback.js"; -import type { PortConfig } from "../define/config.js"; -import type { - BreadboardType, - ConvertBreadboardType, - JsonSerializable, -} from "../type-system/type.js"; -import type { - SerializableInputPort, - SerializableNode, - SerializableOutputPort, -} from "./serializable.js"; - -// TODO(aomarks) Just make this a normal property, no need to export (it was -// originally a symbol to try and make a package-private API). -export const OutputPortGetter = "__output"; - -export const DefaultValue = Symbol(); - -/** - * A Breadboard node port which receives values. - */ -export class InputPort - implements SerializableInputPort -{ - readonly type: BreadboardType; - readonly name: string; - readonly node: SerializableNode; - readonly value?: ValueOrOutputPort | typeof DefaultValue; - readonly #fakeForTypeDiscrimination!: T; - - constructor( - type: BreadboardType, - name: string, - node: SerializableNode, - value: ValueOrOutputPort | typeof DefaultValue - ) { - this.type = type; - this.name = name; - this.node = node; - this.value = value; - } -} - -/** - * A Breadboard node port which sends values. - */ -export class OutputPort - implements OutputPortReference, SerializableOutputPort -{ - readonly [OutputPortGetter] = this; - readonly type: BreadboardType; - readonly name: string; - readonly node: SerializableNode; - readonly #fakeForTypeDiscrimination!: T; - - constructor(type: BreadboardType, name: string, node: SerializableNode) { - this.type = type; - this.name = name; - this.node = node; - } -} - -export interface OutputPortReference { - readonly [OutputPortGetter]: OutputPort; -} - -export function isOutputPortReference( - value: unknown -): value is OutputPortReference { - return ( - typeof value === "object" && value !== null && OutputPortGetter in value - ); -} - -/** - * A map from port name to port config. - */ -export type PortConfigMap = Record; - -/** - * Convert a {@link PortConfigMap} to an object with concrete values for each - * port. - */ -export type ConcreteValues = { - [PortName in keyof Ports]: ConvertBreadboardType; -}; - -export type PortTypes = Record; - -export type ExtractPortTypesFromConfigs = { - [NAME in keyof CONFIGS]: ConvertBreadboardType; -}; - -export type ValuesOrOutputPorts = { - [NAME in keyof TYPES]: ValueOrOutputPort; -}; - -export type PrimaryOutputPort = - GetPrimaryPortType extends never - ? undefined - : OutputPort>>; - -type GetPrimaryPortType = { - [Name in keyof Ports]: Ports[Name] extends { primary: true } - ? Ports[Name] - : never; -}[keyof Ports]["type"]; - -export type InputPorts = { - [PortName in keyof I]: InputPort>; -}; - -export type OutputPorts = { - [PortName in keyof O]: OutputPort>; -}; - -export type ValueOrOutputPort = - | T - | OutputPortReference - | Input - | InputWithDefault - | Loopback; diff --git a/packages/build/src/internal/common/serializable.ts b/packages/build/src/internal/common/serializable.ts deleted file mode 100644 index f8b230fe7c9..00000000000 --- a/packages/build/src/internal/common/serializable.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { GraphMetadata } from "@google-labs/breadboard-schema/graph.js"; -import type { GenericBoardDefinition } from "../board/board.js"; -import type { Convergence } from "../board/converge.js"; -import type { - GenericSpecialInput, - Input, - InputWithDefault, -} from "../board/input.js"; -import type { Loopback } from "../board/loopback.js"; -import type { Output } from "../board/output.js"; -import type { BreadboardType, JsonSerializable } from "../type-system/type.js"; -import type { DefaultValue, OutputPortGetter } from "./port.js"; - -export interface SerializableBoard { - inputs: Record< - string, - | SerializableInputPort - | Input - | InputWithDefault - >; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - inputsForSerialization: any; - // | Record< - // string, - // | SerializableInputPort - // | Input - // | InputWithDefault - // > - // | Array< - // | SerializableInputPort - // | Input - // | InputWithDefault - // >; - outputs: Record< - string, - | SerializableOutputPortReference - | Output - | Input - | InputWithDefault - >; - outputsForSerialization: - | Record< - string, - | SerializableOutputPortReference - | Output - | Input - | InputWithDefault - > - | Array< - Record< - string, - | SerializableOutputPortReference - | Output - | Input - | InputWithDefault - > - >; - id?: string; - title?: string; - description?: string; - version?: string; - metadata?: GraphMetadata; - /** - * A custom describer. It's a separate board that can be - * used to describe the input and output schemas of this - * board. - */ - describer?: GenericBoardDefinition; -} - -export interface SerializableNode { - id?: string; - type: string; - inputs: Record; - metadata?: { - title?: string; - description?: string; - logLevel?: "debug" | "info"; - }; -} - -export interface SerializableInputPort { - name: string; - type: BreadboardType; - node: SerializableNode; - value?: - | JsonSerializable - | SerializableOutputPortReference - | GenericSpecialInput - | Loopback - | Convergence - | GenericBoardDefinition - | typeof DefaultValue; -} - -export interface SerializableOutputPort { - name: string; - type: BreadboardType; - node: SerializableNode; -} - -export interface SerializableOutputPortReference { - [OutputPortGetter]: SerializableOutputPort; -} diff --git a/packages/build/src/internal/common/type-util.ts b/packages/build/src/internal/common/type-util.ts deleted file mode 100644 index dc8a04a23eb..00000000000 --- a/packages/build/src/internal/common/type-util.ts +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * Count the number of items in a type union. - * - * Examples: - * - * never ........... 0 - * "foo" ........... 1 - * "foo" | "bar" ... 2 - */ -export type CountUnion = PermuteUnion["length"]; - -/** - * Generate all permutations of the given union as a union of tuples. - * - * WARNING: This type has quadratic complexity, so it should only be used where - * it is expected that the number of values is very small, such as enforcing - * that something is 0 or 1. - * - * Examples: - * - * never ........... [] - * "foo" ........... ["foo"] - * "foo" | "bar" ... ["foo", "bar"] | ["bar", "foo"] - */ -type PermuteUnion = [U] extends [never] - ? [] - : T extends unknown - ? [T, ...PermuteUnion>] - : never; - -/** - * A hack that encourages TypeScript to expand a type when choosing how to - * display it. Useful for utility types that we don't want to expose directly to - * users. - * - * https://github.com/microsoft/TypeScript/issues/47980#issuecomment-1049304607 - */ -export type Expand = T extends unknown ? { [K in keyof T]: T[K] } : never; - -/** - * Some type, or a promise of it. - */ -export type MaybePromise = T | Promise; - -// eslint-disable-next-line @typescript-eslint/ban-types -export type Defined = {} | null; - -export type BroadenBasicType = - T extends string - ? string - : T extends number - ? number - : T extends boolean - ? boolean - : never; - -/** - * See https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919 - */ -export type IsNever = [T] extends [never] ? true : false; - -/** - * Remove all readonly modifiers on an object. - */ -export type RemoveReadonly = { -readonly [K in keyof T]: T[K] }; - -/** - * For each property in an object, if its value can be `undefined`, mark that - * property as optional. - */ -export type AutoOptional = - T /* See Distributive Conditional Types */ extends unknown - ? { - [K in keyof T as undefined extends T[K] ? K : never]?: T[K]; - } & { [K in keyof T as undefined extends T[K] ? never : K]: T[K] } - : never; - -export type FlattenUnion = { - [K in keyof UnionToIntersection]: K extends keyof T - ? T[K] - : UnionToIntersection[K] | undefined; -}; - -export type UnionToIntersection = ( - U extends unknown ? (k: U) => void : never -) extends (k: infer I) => void - ? I - : never; diff --git a/packages/build/src/internal/common/value.ts b/packages/build/src/internal/common/value.ts deleted file mode 100644 index 9c4e0b4591d..00000000000 --- a/packages/build/src/internal/common/value.ts +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { isConvergence, type Convergence } from "../board/converge.js"; -import { - isSpecialInput, - type Input, - type InputWithDefault, -} from "../board/input.js"; -import { isLoopback, type Loopback } from "../board/loopback.js"; -import { isStarInputs, type StarInputs } from "../board/star-inputs.js"; -import { anyOf } from "../type-system/any-of.js"; -import { - type BreadboardType, - type JsonSerializable, -} from "../type-system/type.js"; -import { - isOutputPortReference, - OutputPort, - OutputPortGetter, - type OutputPortReference, -} from "./port.js"; - -/** - * A value, or something that can stand-in for a value when wiring together - * boards. - * - * For example, for a string, this could be any of: - * - * - An actual string. - * - A string-typed output port. - * - A node with a primary string-typed output port. - * - A string-typed `input`. - */ -export type Value< - T extends JsonSerializable | undefined = JsonSerializable | undefined, -> = - | T - | OutputPort - | OutputPortReference - | Input - | InputWithDefault - | Loopback> - | Convergence>; - -/** - * Given a Breadboard {@link Value}, determine its JSON Schema type. - */ -export function extractTypeFromValue( - value: Value | StarInputs -): BreadboardType { - if (typeof value === "string") { - return "string"; - } - if (typeof value === "number") { - return "number"; - } - if (typeof value === "boolean") { - return "boolean"; - } - if (value === null) { - return "null"; - } - if (isOutputPortReference(value)) { - return value[OutputPortGetter].type; - } - if (isSpecialInput(value)) { - return value.type; - } - if (isLoopback(value)) { - return value.type; - } - if (isConvergence(value)) { - return anyOf( - ...(value.ports.map((port) => extractTypeFromValue(port)) as [ - BreadboardType, - BreadboardType, - ...BreadboardType[], - ]) - ); - } - if (isStarInputs(value)) { - return value.type; - } - return "unknown"; -} diff --git a/packages/build/src/internal/define/config.ts b/packages/build/src/internal/define/config.ts deleted file mode 100644 index 394c7912aff..00000000000 --- a/packages/build/src/internal/define/config.ts +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { BehaviorSchema } from "@google-labs/breadboard"; -import type { BreadboardType, JsonSerializable } from "../type-system/type.js"; - -export type PortConfig = InputPortConfig | OutputPortConfig; -export type PortConfigs = Record; - -export type InputPortConfig = StaticInputPortConfig | DynamicInputPortConfig; -export type OutputPortConfig = StaticOutputPortConfig | DynamicOutputPortConfig; - -/** - * Additional information about the format of the value. Primarily used to - * determine how strings are displayed in the Breadboard Visual Editor. - */ -export type Format = - | /* A string that is likely to contain multiple lines. */ "multiline" - | /* A string that is JavaScript code. */ "javascript"; - -interface BaseConfig { - /** - * The {@link BreadboardType} that values sent or received on this port will - * be required to conform to. - */ - type: BreadboardType; - - /** - * An optional title for the port. Defaults to the name of the port. - */ - title?: string; - - /** - * An optional brief description of this port. Useful when introspecting and - * debugging. - */ - description?: string; - - /** - * Special format annotations. Primarily used as hints for the Breadboard - * visual editor. - */ - format?: Format; - - /** - * Can be used to provide additional hints to the UI or to other parts of - * the system about behavior of this particular input/output or input/output - * port. - */ - behavior?: BehaviorSchema[]; -} - -interface StaticBase { - /** - * If true, this port is is the `primary` input or output port of the node it - * belongs to. - * - * When a node definition has one primary input port, and/or one primary - * output port, then instances of that node will themselves behave like that - * primary input and/or output ports, depending on the context. Note that it - * is an error for a node to have more than 1 primary input ports, or more - * than 1 primary output ports. - * - * For example, an LLM node might have a primary input for `prompt`, and a - * primary output for `completion`. This would mean that in API locations - * where an input port is expected, instead of writing `llm.inputs.prompt`, - * one could simply write `llm`, and the `prompt` port will be selected - * automatically. Likewise for `completion`, where `llm` would be equivalent - * to `llm.outputs.completion` where an output port is expected. - * - * Note this has no effect on Breadboard runtime behavior, it is purely a hint - * to the JavaScript/TypeScript API to help make board construction more - * concise. - */ - primary?: true; -} - -/** - * Configuration for a static import port of a Breadboard node. - */ -export interface StaticInputPortConfig extends BaseConfig, StaticBase { - /** - * A default value for this port. - */ - default?: JsonSerializable; - - /** - * If true, this port is not required and will be passed to `invoke` as - * `undefined`. - */ - optional?: true; -} - -/** - * Configuration for the dynamic import ports of a Breadboard node. - */ -export interface DynamicInputPortConfig extends BaseConfig {} - -/** - * Configuration for a static output port of a Breadboard node. - */ -export interface StaticOutputPortConfig extends BaseConfig, StaticBase {} - -/** - * Configuration for the dynamic output ports of a Breadboard node. - */ -export interface DynamicOutputPortConfig extends BaseConfig { - /** - * If true, for each dynamic input that an instance of this node type is - * instantiated with, an output port with the same name will be automatically - * created. - */ - reflective?: true; -} diff --git a/packages/build/src/internal/define/define.ts b/packages/build/src/internal/define/define.ts deleted file mode 100644 index cf787de6437..00000000000 --- a/packages/build/src/internal/define/define.ts +++ /dev/null @@ -1,423 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/* eslint-disable @typescript-eslint/ban-types */ - -import type { - NodeHandlerContext, - NodeHandlerMetadata, -} from "@google-labs/breadboard"; -import type { - CountUnion, - Expand, - IsNever, - MaybePromise, -} from "../common/type-util.js"; -import type { - ConvertBreadboardType, - JsonSerializable, -} from "../type-system/type.js"; -import type { - DynamicInputPortConfig, - DynamicOutputPortConfig, - InputPortConfig, - OutputPortConfig, - PortConfig, - PortConfigs, - StaticInputPortConfig, - StaticOutputPortConfig, -} from "./config.js"; -import { DefinitionImpl, type Definition } from "./definition.js"; -import type { LooseDescribeFn, StrictDescribeFn } from "./describe.js"; -import type { UnsafeSchema } from "./unsafe-schema.js"; - -/** - * Define a new Breadboard node type. - * - * Note that it is usually preferable to use the `board` function to compose - * existing node types, instead of using this function to define a new node - * type. - * - * The following example is of a monomorphic node, meaning its input and output - * ports are fixed, are the same for all instances, and never change at runtime. - * - * ```ts - * import {defineNodeType} from "@breadboard-ai/build"; - * - * export const reverseString = defineNodeType({ - * name: "reverseString", - * inputs: { - * forwards: { - * type: "string", - * description: "The string to reverse" - * } - * }, - * outputs: { - * backwards: { - * type: "string", - * description: "The reversed string", - * // (Optional) Allow the node itself to act`a shortcut for - * // this output port when wiring up this node in a board. - * primary: true - * } - * }, - * invoke: ({forwards}) => { - * return { - * backwards: forwards.split("").reverse().join("") - * } - * } - * }); - * ``` - * - * The following example is of a polymorphic node, meaning its input and/or - * output ports are allowed to change at runtime. Note the use of the special - * "*" port to signifiy a type constraint that applies to all dynamic ports. - * - * ```ts - * import { defineNodeType, anyOf } from "@breadboard-ai/build"; - * - * export const templater = defineNodeType({ - * name: "templater", - * inputs: { - * template: { - * type: "string", - * description: "A template with {{placeholders}}.", - * }, - * "*": { - * type: anyOf("string", "number"), - * description: "Values to fill into template's placeholders.", - * }, - * }, - * outputs: { - * result: { - * type: "string", - * description: "The template with placeholders substituted.", - * }, - * }, - * describe: ({ template }) => { - * return { - * inputs: Object.fromEntries( - * extractPlaceholders(template ?? "").map((name) => [ - * name, - * { type: anyOf("string", "number") }, - * ]) - * ), - * }; - * }, - * invoke: ({ template }, placeholders) => { - * return { - * result: substituteTemplatePlaceholders(template, placeholders), - * }; - * }, - * }); - * ``` - * - * @param inputs An object that maps from input port name to the - * {@link PortConfig} for that input port. - * @param output An object that maps from output port name to the - * {@link PortConfig} for that output port. - * @param invoke The function that will be called when this node is active in a - * board. Receives an object that maps from input port name to the most recent - * concrete value received on that port. Returns an object that maps from output - * port name to the oncrete value that should be sent on that port. - * @return A {@link NodeDefinition} which can be instantiated, whose outputs can - * be wired to the inputs of other nodes, and which can be encapsulated into a - * `board` for execution. - */ -export function defineNodeType< - I extends Record, - O extends Record, - F extends LooseInvokeFn, - D extends VeryLooseDescribeFn, ->( - params: { - // Start with a loose type to help TypeScript bind the generics. - name: string; - inputs: I; - outputs: O; - invoke: F; - describe?: D; - metadata?: NodeHandlerMetadata; - } & { - // Then narrow down the types with further constraints. This 2-step - // approach lets us generate additional and more precise errors. - inputs: StrictInputs; - outputs: StrictOutputs; - invoke: StrictInvokeFn; - } & StrictDescribeFn -): Definition< - Expand>, - Expand>, - GetDynamicTypes, - GetDynamicTypes, - GetOptionalInputs & keyof Expand>, - GetReflective, - Expand>, - Expand>, - Expand> -> { - if (!params.name) { - throw new Error("params.name is required"); - } - if (!params.inputs) { - throw new Error("params.inputs is required"); - } - if (!params.outputs) { - throw new Error("params.outputs is required"); - } - if (!params.invoke) { - throw new Error("params.invoke is required"); - } - const impl = new DefinitionImpl< - Expand>, - Expand>, - GetDynamicTypes, - GetDynamicTypes, - GetOptionalInputs & keyof Expand>, - GetReflective, - Expand>, - Expand>, - Expand> - >( - params.name, - omitDynamic(params.inputs), - omitDynamic(params.outputs), - params.inputs["*"], - params.outputs["*"], - primary(params.inputs), - primary(params.outputs), - params.invoke as Function as VeryLooseInvokeFn, - params.describe as LooseDescribeFn - ); - return Object.assign(impl.instantiate.bind(impl), { - breadboardType: "DiscreteComponent", - id: params.name, - invoke: impl.invoke.bind(impl), - describe: impl.describe.bind(impl), - metadata: params.metadata || {}, - // TODO(aomarks) Should not need cast. - }) as Definition< - Expand>, - Expand>, - GetDynamicTypes, - GetDynamicTypes, - GetOptionalInputs & keyof Expand>, - GetReflective, - Expand>, - Expand>, - Expand> - >; -} - -type ExtractInputMetadata> = { - [K in keyof I as K extends "*" ? never : K]: { - board: I[K]["behavior"] extends Array - ? "board" extends I[K]["behavior"][number] - ? true - : false - : false; - }; -}; - -function omitDynamic(configs: PortConfigs): PortConfigs { - return Object.fromEntries( - Object.entries(configs).filter(([name]) => name !== "*") - ); -} - -function primary(configs: PortConfigs): keyof typeof configs | undefined { - const primaries = Object.entries(configs).filter( - ([, config]) => "primary" in config && config.primary - ); - if (primaries.length > 1) { - throw new Error("Too many primaries"); - } - return primaries[0]?.[0]; -} - -type StrictInputs> = { - [K in keyof I]: K extends "$id" | "$metadata" - ? never - : K extends "*" - ? StrictMatch - : StrictMatch< - I[K], - GetDefault extends JsonSerializable - ? StaticInputPortConfig & { - default: Convert; - optional: never; - } - : StaticInputPortConfig - >; -} & ForbidMultiplePrimaries; - -type StrictOutputs> = { - [K in keyof O]: K extends "$error" - ? never - : K extends "*" - ? StrictMatch - : StrictMatch; -} & ForbidMultiplePrimaries; - -type GetDefault = I extends StaticInputPortConfig - ? I["default"] - : undefined; - -/** - * Check that ACTUAL is assignable to EXPECTED and that there are no excess - * properties. - */ -type StrictMatch = { - [K in keyof ACTUAL]: K extends keyof EXPECTED ? EXPECTED[K] : never; -}; - -type ForbidMultiplePrimaries> = - CountUnion> extends 0 | 1 - ? C - : { [K in keyof C]: Omit & { primary: never } }; - -type PrimaryPortNames> = { - [K in keyof C]: C[K] extends StaticInputPortConfig | StaticOutputPortConfig - ? C[K]["primary"] extends true - ? K - : never - : never; -}[keyof C]; - -type LooseInvokeFn> = Expand< - ( - staticParams: Expand>, - dynamicParams: Expand> - ) => MaybePromise<{ [K: string]: JsonSerializable }> ->; - -export type VeryLooseInvokeFn = ( - staticParams: Record, - dynamicParams: Record, - context: NodeHandlerContext -) => { [K: string]: JsonSerializable | undefined }; - -type StrictInvokeFn< - I extends Record, - O extends Record, - F extends LooseInvokeFn, -> = ( - staticInputs: Expand>, - dynamicInputs: Expand>, - context: NodeHandlerContext -) => MaybePromise>; - -type StrictInvokeFnReturn< - I extends Record, - O extends Record, - F extends LooseInvokeFn, -> = - ReturnType unknown ? F : never> extends { - $error: unknown; - } - ? { - [K in keyof ReturnType< - F extends (...args: unknown[]) => unknown ? F : never - >]: K extends "$error" - ? - | string - | { message: string } - | { kind: string; error: { message: string } } - : never; - } - : { - [K in keyof Omit]: Convert; - } & { - [K in keyof ReturnType< - F extends (...args: unknown[]) => unknown ? F : never - >]: K extends keyof O - ? Convert - : O["*"] extends DynamicOutputPortConfig - ? Convert - : never; - }; - -export type StaticInvokeParams> = { - [K in keyof Omit]: I[K] extends StaticInputPortConfig - ? I[K]["optional"] extends true - ? Convert | undefined - : Convert - : Convert; -}; - -export type DynamicInvokeParams> = - I["*"] extends DynamicInputPortConfig - ? { [K: string]: Convert } - : // eslint-disable-next-line @typescript-eslint/ban-types - {}; - -type GetStaticTypes> = { - [K in Exclude]: K extends "*" ? never : Convert; -}; - -type GetOptionalInputs> = { - [K in keyof I]: I[K] extends StaticInputPortConfig - ? I[K]["optional"] extends true - ? K - : I[K]["default"] extends JsonSerializable - ? K - : never - : never; -}[keyof I]; - -type GetDynamicTypes> = - C["*"] extends PortConfig ? Convert : undefined; - -type GetPrimary> = ReplaceNever< - Extract< - { - [K in keyof Omit]: C[K] extends - | StaticInputPortConfig - | StaticOutputPortConfig - ? C[K]["primary"] extends true - ? K - : false - : false; - }[keyof Omit], - string - >, - false ->; - -type ReplaceNever = IsNever extends true ? R : T; - -type GetReflective> = - O["*"] extends DynamicOutputPortConfig - ? O["*"]["reflective"] extends true - ? true - : false - : false; - -type Convert = ConvertBreadboardType; - -type VeryLooseDescribeFn = Function; - -export type CustomDescribePortManifest = - | string[] - | { - [K: string]: - | { description?: string } - // We include undefined here because TypeScript sometimes generates a - // type which would otherwise not match our constraint. For example, - // the expression: - // - // outputFoo ? { foo: { description: "foo" } } : {} - // - // Gets assigned this type: - // - // { foo: { description:"foo" } } | { foo?: undefined } - // - // Instead of: - // - // { foo: { description:"foo" } } | {} - | undefined; - } - | UnsafeSchema; diff --git a/packages/build/src/internal/define/definition.ts b/packages/build/src/internal/define/definition.ts deleted file mode 100644 index 4de3aa6fffe..00000000000 --- a/packages/build/src/internal/define/definition.ts +++ /dev/null @@ -1,579 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - InputValues, - NodeDescriberContext, - NodeDescriberResult, - NodeHandlerContext, - NodeHandlerMetadata, - OutputValues, - Schema, -} from "@google-labs/breadboard"; -import type { JSONSchema4 } from "json-schema"; -import type { Input, InputWithDefault } from "../board/input.js"; -import type { Loopback } from "../board/loopback.js"; -import type { StrictNodeHandler } from "../common/compatibility.js"; -import type { OutputPortReference } from "../common/port.js"; -import type { Expand } from "../common/type-util.js"; -import { - toJSONSchema, - type BreadboardType, - type JsonSerializable, -} from "../type-system/type.js"; -import type { - DynamicInputPortConfig, - DynamicOutputPortConfig, - PortConfig, - PortConfigs, - StaticInputPortConfig, - StaticOutputPortConfig, -} from "./config.js"; -import type { - CustomDescribePortManifest, - VeryLooseInvokeFn, -} from "./define.js"; -import type { LooseDescribeFn } from "./describe.js"; -import { Instance } from "./instance.js"; -import { - jsonSchemaToPortConfigMap, - portConfigMapToJSONSchema, -} from "./json-schema.js"; -import { - isUnsafeSchema, - unsafeSchemaAccessor, - type UnsafeSchema, -} from "./unsafe-schema.js"; -import { unsafeType } from "../type-system/unsafe.js"; -import { array } from "../type-system/array.js"; -import { object } from "../type-system/object.js"; -import { normalizeBreadboardError } from "../common/error.js"; -import type { Convergence } from "../board/converge.js"; -import type { SerializableBoard } from "../common/serializable.js"; -import type { StarInputs } from "../board/star-inputs.js"; -import type { KitBinding } from "../kit.js"; - -export interface Definition< - /* Static Inputs */ SI extends { - [K: string]: JsonSerializable | undefined; - }, - /* Static Outputs */ SO extends { - [K: string]: JsonSerializable | undefined; - }, - /* Dynamic Inputs */ DI extends JsonSerializable | undefined, - /* Dynamic Outputs */ DO extends JsonSerializable | undefined, - /* Optional Inputs */ OI extends keyof SI, - /* Reflective? */ R extends boolean, - /* Primary Input */ PI extends string | false, - /* Primary Output */ PO extends string | false, - /* Input Metadata */ IM extends { [K: string]: InputMetadata }, -> extends StrictNodeHandler { - breadboardType: "DiscreteComponent"; - id: string; - metadata: NodeHandlerMetadata; - ( - args: A & StrictInstantiateArgs - ): Instance< - InstanceInputs, - InstanceOutputs, - R extends true ? undefined : DO, - PI, - PO, - R - >; -} - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export type GenericDiscreteComponent = Definition< - any, - any, - any, - any, - any, - any, - any, - any, - any ->; -/* eslint-enable @typescript-eslint/no-explicit-any */ - -export function isDiscreteComponent( - value: object -): value is GenericDiscreteComponent { - return ( - "breadboardType" in value && value.breadboardType === "DiscreteComponent" - ); -} - -export class DefinitionImpl< - /* Static Inputs */ SI extends { - [K: string]: JsonSerializable | undefined; - }, - /* Static Outputs */ SO extends { - [K: string]: JsonSerializable | undefined; - }, - /* Dynamic Inputs */ DI extends JsonSerializable | undefined, - /* Dynamic Outputs */ DO extends JsonSerializable | undefined, - /* Optional Inputs */ OI extends keyof SI, - /* Reflective? */ R extends boolean, - /* Primary Input */ PI extends string | false, - /* Primary Output */ PO extends string | false, - /* Input Metadata */ IM extends { [K: string]: InputMetadata }, -> implements StrictNodeHandler -{ - readonly #name: string; - readonly #staticInputs: Record; - readonly #staticOutputs: PortConfigs; - readonly #dynamicInputs: DynamicInputPortConfig | undefined; - readonly #dynamicOutputs: PortConfig | undefined; - readonly #reflective: boolean; - readonly #primaryInput: string | undefined; - readonly #primaryOutput: string | undefined; - readonly #invoke: VeryLooseInvokeFn; - readonly #describe?: LooseDescribeFn; - - constructor( - name: string, - staticInputs: PortConfigs, - staticOutputs: PortConfigs, - dynamicInputs: PortConfig | undefined, - dynamicOutputs: DynamicOutputPortConfig | undefined, - primaryInput: string | undefined, - primaryOutput: string | undefined, - invoke: VeryLooseInvokeFn, - describe?: LooseDescribeFn - ) { - if ("$id" in staticInputs) { - throw new Error( - '"$id" cannot be used as an input port name because it is reserved' - ); - } - if ("$metadata" in staticInputs) { - throw new Error( - '"$metadata" cannot be used as an input port name because it is reserved' - ); - } - if ("$error" in staticOutputs) { - throw new Error( - '"$error" cannot be used as an output port name because it is reserved' - ); - } - this.#name = name; - this.#staticInputs = staticInputs; - this.#staticOutputs = staticOutputs; - this.#dynamicInputs = dynamicInputs; - this.#dynamicOutputs = dynamicOutputs; - this.#reflective = dynamicOutputs?.reflective ?? false; - this.#primaryInput = primaryInput; - this.#primaryOutput = primaryOutput; - this.#invoke = invoke; - this.#describe = describe; - } - - instantiate( - args: A & StrictInstantiateArgs, - kitBinding?: KitBinding - ): Instance< - InstanceInputs, - InstanceOutputs, - R extends true ? undefined : DO, - PI, - PO, - R - > { - if (!args) { - throw new Error("args is required"); - } - return new Instance( - this.#name, - this.#staticInputs, - this.#dynamicInputs, - this.#staticOutputs, - this.#dynamicOutputs, - this.#reflective, - // TODO(aomarks) Fix - // eslint-disable-next-line @typescript-eslint/no-explicit-any - args as any, - kitBinding - ); - } - - async invoke( - values: InputValues, - context: NodeHandlerContext - ): Promise { - const { staticValues, dynamicValues } = - this.#applyDefaultsAndPartitionRuntimeInputValues(values); - let result; - try { - result = await this.#invoke(staticValues, dynamicValues, context); - } catch (e) { - return { - $error: { - message: `Internal Exception: ${String(e instanceof Error ? e.stack : e).replace(/^Error:\s*/, "")}`, - }, - }; - } - if (result.$error !== undefined) { - result.$error = normalizeBreadboardError(result.$error); - } - return result; - } - - /** - * Apply defaults, and split the values between static and dynamic ports. - * - * We split inputs values for type safety, because in TypeScript it is - * unfortunately not possible to define an object where the values of the - * unknown keys are of one type, and the known keys are of an incompatible - * type. - */ - #applyDefaultsAndPartitionRuntimeInputValues(values: InputValues): { - staticValues: Record; - dynamicValues: Record; - } { - const staticValues: Record = {}; - const dynamicValues: Record = {}; - for (const [name, config] of Object.entries(this.#staticInputs)) { - if (config.default !== undefined) { - staticValues[name] = config.default; - } - } - for (const [name, value] of Object.entries(values)) { - if (this.#staticInputs[name] !== undefined) { - staticValues[name] = value as JsonSerializable; - } else { - dynamicValues[name] = value as JsonSerializable; - } - } - return { - // TODO(aomarks) Validate schema before passing to invoke function. - staticValues, - dynamicValues, - }; - } - - async describe( - values?: InputValues, - inboundEdges?: Schema, - outboundEdges?: Schema, - context?: NodeDescriberContext - ): Promise { - let user: - | { - inputs?: CustomDescribePortManifest; - outputs?: CustomDescribePortManifest; - } - | undefined = undefined; - if (this.#describe !== undefined) { - const { staticValues, dynamicValues } = - this.#applyDefaultsAndPartitionRuntimeInputValues(values ?? {}); - user = await this.#describe(staticValues, dynamicValues, { - ...(context ?? { - outerGraph: { nodes: [], edges: [] }, - wires: { incoming: {}, outgoing: {} }, - }), - inputSchema: jsonSchemaToPortConfigMap( - (inboundEdges as JSONSchema4) ?? {} - ), - outputSchema: jsonSchemaToPortConfigMap( - (outboundEdges as JSONSchema4) ?? {} - ), - }); - } - - let inputSchema: JSONSchema4 & { - properties?: { [k: string]: JSONSchema4 }; - }; - if (isUnsafeSchema(user?.inputs)) { - inputSchema = mergeStaticsAndUnsafeUserSchema( - portConfigMapToJSONSchema(this.#staticInputs, []), - user.inputs[unsafeSchemaAccessor] - ); - } else if (this.#dynamicInputs === undefined) { - // All inputs are static. - inputSchema = { - ...portConfigMapToJSONSchema(this.#staticInputs, []), - additionalProperties: false, - }; - } else if (user?.inputs !== undefined) { - // The definition author has provided the inputs. - const { newStatic, newDynamic } = parseDynamicPorts( - user.inputs, - this.#dynamicInputs - ); - inputSchema = portConfigMapToJSONSchema( - { ...newStatic, ...this.#staticInputs }, - // TODO(aomarks) The user should be able to indicate from their describe - // function whether a specific input is optional/required. - [] - ); - if (newDynamic === undefined) { - inputSchema.additionalProperties = false; - } else if (newDynamic.type === "unknown") { - inputSchema.additionalProperties = true; - } else { - inputSchema.additionalProperties = toJSONSchema(newDynamic.type); - } - } else { - // No definition author inputs, assume all actual inputs are valid. - const actualInputNames = [ - ...new Set([ - ...Object.keys(values ?? {}), - ...Object.keys(inboundEdges?.properties ?? {}), - ]), - ].sort(); - const actualDynamicInputNames = actualInputNames.filter( - // Only include the actual input names that aren't in our static inputs. - (name) => this.#staticInputs[name] === undefined - ); - const dynamicInputConfig = this.#dynamicInputs; - const getInputType = (name: string): BreadboardType => { - const fromInbound = inboundEdges?.properties?.[name]; - if (fromInbound) { - return unsafeType(fromInbound as JSONSchema4); - } - const fromValues = values?.[name]; - if (fromValues !== undefined) { - return inferType(fromValues); - } - return dynamicInputConfig.type; - }; - inputSchema = { - ...portConfigMapToJSONSchema( - { - ...Object.fromEntries( - actualInputNames.map((name) => [ - name, - { type: getInputType(name) }, - ]) - ), - ...this.#staticInputs, - }, - actualDynamicInputNames - ), - additionalProperties: - this.#dynamicInputs.type === "unknown" - ? true - : toJSONSchema(this.#dynamicInputs.type), - }; - } - - let outputSchema: JSONSchema4 & { - properties?: { [k: string]: JSONSchema4 }; - }; - if (isUnsafeSchema(user?.outputs)) { - outputSchema = mergeStaticsAndUnsafeUserSchema( - portConfigMapToJSONSchema(this.#staticOutputs, true), - user.outputs[unsafeSchemaAccessor] - ); - } else if (this.#dynamicOutputs === undefined) { - // All outputs are static. - outputSchema = { - ...portConfigMapToJSONSchema( - this.#staticOutputs, - // TODO(aomarks) The Breadboard visual editor interprets JSON schema - // "required" on an output as "the user must wire this to something" - // (shows up as a red port). That might be not quite right, it seems - // like "required" here should describe the expectations of the node - // implementation's return object, not the way the user choses to use - // the output. - true - ), - additionalProperties: false, - }; - } else if (this.#reflective) { - // We're reflective, so our outputs are determined by our dynamic inputs. - const dynamicInputs = Object.entries(inputSchema.properties ?? {}).filter( - ([name]) => this.#staticInputs[name] === undefined - ); - outputSchema = { - ...portConfigMapToJSONSchema( - { - ...Object.fromEntries( - dynamicInputs.map(([name, schema]) => [ - name, - { type: unsafeType(schema) }, - ]) - ), - ...this.#staticOutputs, - }, - true - ), - additionalProperties: false, - }; - } else if (user?.outputs !== undefined) { - // The definition author has provided the outputs. - const { newStatic, newDynamic } = parseDynamicPorts( - user.outputs, - this.#dynamicOutputs - ); - outputSchema = portConfigMapToJSONSchema( - { - ...newStatic, - ...this.#staticOutputs, - }, - true - ); - if (newDynamic === undefined) { - outputSchema.additionalProperties = false; - } else if (newDynamic.type === "unknown") { - outputSchema.additionalProperties = true; - } else { - outputSchema.additionalProperties = toJSONSchema(newDynamic.type); - } - } else { - outputSchema = { - ...portConfigMapToJSONSchema(this.#staticOutputs, true), - additionalProperties: toJSONSchema(this.#dynamicOutputs.type), - }; - } - - return { - inputSchema: inputSchema as Schema, - outputSchema: outputSchema as Schema, - }; - } -} - -/** - * Extra data about inputs. This is here to stop growing the number of - * parameters on Definition. - */ -export type InputMetadata = { - board: boolean; -}; - -function parseDynamicPorts( - ports: Exclude, - base: DynamicInputPortConfig | DynamicOutputPortConfig -): { - newStatic: Record; - newDynamic: DynamicInputPortConfig | DynamicOutputPortConfig | undefined; -} { - ports = Array.isArray(ports) - ? Object.fromEntries(ports.map((name) => [name, {}])) - : ports; - const newStatic = Object.fromEntries( - Object.entries(ports) - .filter( - /** See {@link CustomDescribePortManifest} for why undefined is possible here. */ - ([name, config]) => config !== undefined && name !== "*" - ) - .map(([name, config]) => [name, { ...base, ...config }]) - ); - const newDynamic = - ports["*"] !== undefined ? { ...base, ...ports["*"] } : undefined; - return { newStatic, newDynamic }; -} - -type LooseInstantiateArgs = object; - -type StrictInstantiateArgs< - SI extends { [K: string]: JsonSerializable | undefined }, - OI extends keyof SI, - DI extends JsonSerializable | undefined, - A extends LooseInstantiateArgs, - IM extends { [K: string]: InputMetadata }, -> = { - $id?: string; - $metadata?: { - title?: string; - description?: string; - }; - "*"?: StarInputs; -} & { - [K in keyof Omit]: IM[K extends keyof IM - ? K - : never]["board"] extends true - ? InstantiateArg | SerializableBoard - : InstantiateArg; -} & { - [K in OI]?: - | InstantiateArg - | OutputPortReference - | undefined; -} & { - [K in keyof Omit< - A, - keyof SI | "$id" | "$metadata" | "*" - >]: DI extends JsonSerializable ? InstantiateArg : never; -}; - -type InstanceInputs< - SI extends { [K: string]: JsonSerializable | undefined }, - DI extends JsonSerializable | undefined, - A extends LooseInstantiateArgs, -> = Expand< - SI & { - [K in keyof Omit]: K extends keyof SI ? SI[K] : DI; - } ->; - -type InstanceOutputs< - SI extends { [K: string]: JsonSerializable | undefined }, - SO extends { [K: string]: JsonSerializable | undefined }, - DO extends JsonSerializable | undefined, - R extends boolean, - A extends LooseInstantiateArgs, -> = R extends true - ? Expand]: DO }> - : SO; - -type InstantiateArg = - | T - | OutputPortReference - | Input - | InputWithDefault - | Loopback> - | Convergence>; - -function mergeStaticsAndUnsafeUserSchema( - statics: JSONSchema4, - unsafe: JSONSchema4 -): JSONSchema4 { - const merged = { ...statics, ...unsafe }; - if (statics.properties || unsafe.properties) { - merged.properties = { ...statics.properties, ...unsafe.properties }; - } - // The JSON Schema types say that required can be boolean, but there is - // no evidence for that in the JSON Schema documentation. - const aRequired = statics.required as Exclude< - JSONSchema4["required"], - boolean - >; - const bRequired = unsafe.required as Exclude< - JSONSchema4["required"], - boolean - >; - if (aRequired || bRequired) { - merged.required = [ - ...new Set([...(aRequired ?? []), ...(bRequired ?? [])]), - ]; - } - return merged; -} - -function inferType(value: unknown): BreadboardType { - const t = typeof value; - switch (t) { - case "string": - case "number": - case "boolean": { - return t; - } - case "object": { - if (value === null) { - return "null"; - } - if (Array.isArray(value)) { - return array("unknown"); - } - return object({}, "unknown"); - } - } - return "unknown"; -} diff --git a/packages/build/src/internal/define/describe.ts b/packages/build/src/internal/define/describe.ts deleted file mode 100644 index 2a79e5d9142..00000000000 --- a/packages/build/src/internal/define/describe.ts +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { NodeDescriberContext } from "@google-labs/breadboard"; -import type { Expand, MaybePromise } from "../common/type-util.js"; -import type { - ConvertBreadboardType, - JsonSerializable, -} from "../type-system/type.js"; -import type { - DynamicInputPortConfig, - DynamicOutputPortConfig, - InputPortConfig, - OutputPortConfig, - PortConfig, - StaticInputPortConfig, - StaticOutputPortConfig, -} from "./config.js"; -import type { - CustomDescribePortManifest, - DynamicInvokeParams, -} from "./define.js"; - -/** - * The same as {@link NodeDescriberContext} but with `inputSchema ` and - * `outputSchema` added in, to simplify the signature of `describe`. - * - * TODO(aomarks) Roll this into {@link NodeDescriberContext}. - */ -export interface NodeDescriberContextWithSchemas extends NodeDescriberContext { - inputSchema: { [k: string]: StaticInputPortConfig }; - outputSchema: { [k: string]: StaticOutputPortConfig }; -} - -export type LooseDescribeFn = ( - staticParams: Record, - dynamicParams: Record, - context?: NodeDescriberContextWithSchemas -) => MaybePromise<{ - inputs?: CustomDescribePortManifest; - outputs?: CustomDescribePortManifest; -}>; - -export type StaticDescribeValues> = { - [K in keyof Omit]: I[K] extends StaticInputPortConfig - ? I[K]["default"] extends JsonSerializable - ? Convert - : Convert | undefined - : Convert; -}; - -type Convert = ConvertBreadboardType; - -export type StrictDescribeFn< - I extends Record, - O extends Record, -> = I["*"] extends DynamicInputPortConfig - ? O["*"] extends DynamicOutputPortConfig - ? O["*"]["reflective"] extends true - ? { - // poly/poly reflective - describe?: ( - staticInputs: Expand>, - dynamicInputs: Expand>, - context?: NodeDescriberContextWithSchemas - ) => MaybePromise<{ - inputs: CustomDescribePortManifest; - outputs?: never; - }>; - } - : { - // poly/poly non-reflective - describe: ( - staticInputs: Expand>, - dynamicInputs: Expand>, - context?: NodeDescriberContextWithSchemas - ) => MaybePromise<{ - inputs?: CustomDescribePortManifest; - outputs: CustomDescribePortManifest; - }>; - } - : { - // poly/mono - describe?: ( - staticInputs: Expand>, - dynamicInputs: Expand>, - context?: NodeDescriberContextWithSchemas - ) => MaybePromise<{ - inputs: CustomDescribePortManifest; - outputs?: never; - }>; - } - : O["*"] extends DynamicOutputPortConfig - ? { - // mono/poly - describe: ( - staticInputs: Expand>, - dynamicInputs: Expand>, - context?: NodeDescriberContextWithSchemas - ) => MaybePromise<{ - inputs?: never; - outputs: CustomDescribePortManifest; - }>; - } - : { - // mono/mono - describe?: never; - }; diff --git a/packages/build/src/internal/define/instance.ts b/packages/build/src/internal/define/instance.ts deleted file mode 100644 index 48424ecfe00..00000000000 --- a/packages/build/src/internal/define/instance.ts +++ /dev/null @@ -1,257 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/* eslint-disable @typescript-eslint/ban-types */ - -import { breadboardErrorType, type BreadboardError } from "../common/error.js"; -import { - DefaultValue, - InputPort, - OutputPort, - OutputPortGetter, - type OutputPortReference, -} from "../common/port.js"; -import type { SerializableNode } from "../common/serializable.js"; -import type { KitBinding } from "../kit.js"; -import type { BreadboardType, JsonSerializable } from "../type-system/type.js"; -import type { - DynamicInputPortConfig, - DynamicOutputPortConfig, - StaticInputPortConfig, - StaticOutputPortConfig, -} from "./config.js"; - -export class Instance< - /* Inputs */ I extends { [K: string]: JsonSerializable | undefined }, - /* Outputs */ O extends { [K: string]: JsonSerializable | undefined }, - /* Dynamic Output */ DO extends JsonSerializable | undefined, - /* Primary Input */ PI extends string | false, - /* Primary Output */ PO extends string | false, - /* Reflective */ R extends boolean, -> implements SerializableNode -{ - readonly id?: string; - readonly type: string; - readonly inputs: { [K in keyof I]: InputPort> }; - readonly outputs: { - [K in keyof O | "$error"]: K extends "$error" - ? OutputPort - : OutputPort; - }; - readonly primaryInput: PI extends keyof I - ? InputPort> - : undefined; - readonly primaryOutput: PO extends keyof O ? OutputPort : undefined; - // TODO(aomarks) Clean up output port getter - readonly [OutputPortGetter]: PO extends keyof O - ? OutputPort - : undefined; - readonly #dynamicInputType?: BreadboardType; - readonly #dynamicOutputType?: BreadboardType; - readonly #reflective: boolean; - readonly metadata?: { title: string; description: string }; - - constructor( - type: string, - staticInputs: { [K: string]: StaticInputPortConfig }, - dynamicInputs: DynamicInputPortConfig | undefined, - staticOutputs: { [K: string]: StaticOutputPortConfig }, - dynamicOutputs: DynamicOutputPortConfig | undefined, - reflective: boolean, - args: { - [K: string]: JsonSerializable | OutputPortReference; - } & { $id?: string }, - kitBinding?: KitBinding - ) { - this.type = kitBinding?.id ?? type; - this.#dynamicInputType = dynamicInputs?.type; - this.#dynamicOutputType = dynamicOutputs?.type; - this.#reflective = reflective; - - this.id = args["$id"]; - if (this.id !== undefined) { - args = { ...args }; - delete args["$id"]; - } - - { - const { ports, primary, metadata } = this.#processInputs( - staticInputs, - args - ); - this.inputs = ports as (typeof this)["inputs"]; - this.primaryInput = primary as (typeof this)["primaryInput"]; - this.metadata = metadata as (typeof this)["metadata"]; - } - - { - const { ports, primary } = this.#processOutputs( - staticInputs, - staticOutputs, - args - ); - this.outputs = ports as (typeof this)["outputs"]; - this.primaryOutput = primary as (typeof this)["primaryOutput"]; - this[OutputPortGetter] = primary as (typeof this)["primaryOutput"]; - } - } - - #assertedOutputs = new Map>(); - - unsafeOutput: DO extends JsonSerializable - ? R extends false - ? ( - name: N extends keyof O ? never : N - ) => OutputPort - : never - : never = ((name) => { - if (this.#dynamicOutputType === undefined) { - throw new Error( - `unsafeOutput was called unnecessarily on a BreadboardNode. ` + - `Type "${this.type}" has entirely static outputs. ` + - `Use ".outputs.${name}" instead.` - ); - } - if (this.#reflective) { - throw new Error( - `unsafeOutput was called unnecessarily on a BreadboardNode. ` + - `Type "${this.type}" is reflective. ` + - `Use ".outputs.${name}" instead.` - ); - } - if (this.outputs[name] !== undefined) { - throw new Error( - `unsafeOutput was called unnecessarily on a BreadboardNode. ` + - `Type "${this.type}" already has a static port called "${name}". ` + - `Use ".outputs.${name}" instead.` - ); - } - let port = this.#assertedOutputs.get(name); - if (port !== undefined) { - return port; - } - port = new OutputPort(this.#dynamicOutputType, name, this); - this.#assertedOutputs.set(name, port); - return port; - }) as (typeof this)["unsafeOutput"]; - - #processInputs( - staticInputs: { [K: string]: StaticInputPortConfig }, - args: { - [K: string]: JsonSerializable | OutputPortReference; - } - ) { - const ports: { [K: string]: InputPort } = {}; - let primary: InputPort | undefined = undefined; - - const metadata = args["$metadata"]; - if (metadata !== undefined) { - args = { ...args }; - delete args["$metadata"]; - } - - // Static inputs - for (const [name, config] of Object.entries(staticInputs)) { - const arg = args[name]; - if ( - arg === undefined && - config.optional !== true && - config.default === undefined - ) { - throw new Error(`Argument ${name} is required`); - } - const port = new InputPort(config.type, name, this, arg ?? DefaultValue); - ports[name] = port; - if (config.primary) { - if (this.primaryInput !== undefined) { - throw new Error("More than one primary input"); - } - primary = port; - } - } - - // Dynamic inputs - for (const [name, arg] of Object.entries(args)) { - if (staticInputs[name] !== undefined) { - // Static input, already handled. - continue; - } - if (this.#dynamicInputType === undefined) { - throw new Error(`Unexpected input: ${name}`); - } - const port = new InputPort(this.#dynamicInputType, name, this, arg); - ports[name] = port; - } - - return { ports, primary, metadata }; - } - - #processOutputs( - staticInputs: { [K: string]: StaticInputPortConfig }, - staticOutputs: { [K: string]: StaticOutputPortConfig }, - args: { - [K: string]: JsonSerializable | OutputPortReference; - } - ) { - const ports: { [K: string]: OutputPort } & { - assert?: (name: string) => OutputPort; - } = { - $error: new OutputPort(breadboardErrorType, "$error", this), - }; - let primary: OutputPort | undefined = - undefined; - - for (const [name, config] of Object.entries(staticOutputs)) { - const port = new OutputPort(config.type, name, this); - ports[name] = port; - if (config.primary) { - if (primary !== undefined) { - throw new Error("More than one primary output"); - } - primary = port; - } - } - - if (this.#dynamicOutputType !== undefined) { - const type = this.#dynamicOutputType; - if (this.#reflective) { - // For reflective nodes, we know immediately at instantiation time what - // all the output ports are, because it's determined entirely by the - // inputs, which are exhaustively initialized at instantiation. - for (const name of Object.keys(args)) { - if (staticInputs[name] !== undefined) { - // Static input, doesn't reflect. - continue; - } - const port = new OutputPort(type, name, this); - ports[name] = port; - } - } else { - // For other (non-reflective) nodes that have dynamic outputs, we can't - // know at initialization time what ports exist, since that's up to the - // describe function. - // - // However, we do need some way to let the user create references to - // these ports. One approach would be to make ports a Proxy object, and - // create the OutputPort any time there is a property access. But, we - // want to make it clear to see when a port is being asserted, since the - // type system has absolutely no idea if this is a valid port or not. - ports.assert = ( - name: string - ): OutputPort => { - let port = ports[name]; - if (port !== undefined) { - return port; - } - port = new OutputPort(type, name, this); - ports[name] = port; - return port; - }; - } - } - return { ports, primary }; - } -} diff --git a/packages/build/src/internal/define/json-schema.ts b/packages/build/src/internal/define/json-schema.ts deleted file mode 100644 index e353e3be1a9..00000000000 --- a/packages/build/src/internal/define/json-schema.ts +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { JSONSchema4 } from "json-schema"; -import type { PortConfigMap } from "../common/port.js"; -import { toJSONSchema } from "../type-system/type.js"; -import type { - Format, - StaticInputPortConfig, - StaticOutputPortConfig, -} from "./config.js"; -import { unsafeType } from "../type-system/unsafe.js"; - -export function portConfigMapToJSONSchema( - config: PortConfigMap, - forceOptional: string[] | /* all */ true -): JSONSchema4 & { - properties?: { [k: string]: JSONSchema4 }; -} { - const sortedPropertyEntries = Object.entries(config).sort( - ([nameA], [nameB]) => nameA.localeCompare(nameB) - ); - const forceOptionalSet = new Set( - forceOptional === true ? Object.keys(config) : forceOptional - ); - return { - type: "object", - properties: Object.fromEntries( - sortedPropertyEntries.map( - ([name, { title, description, type, behavior, ...config }]) => { - const schema: JSONSchema4 = { - ...toJSONSchema(type), - title: title ?? name, - }; - if (description) { - schema.description = description; - } - const defaultValue = (config as StaticInputPortConfig).default; - if (defaultValue !== undefined) { - schema.default = defaultValue; - } - if (config.format !== undefined) { - schema.format = config.format; - } - if (behavior !== undefined && behavior.length > 0) { - schema.behavior = behavior; - } - return [name, schema]; - } - ) - ), - required: sortedPropertyEntries - .filter(([name, config]) => { - const isOptional = (config as StaticInputPortConfig).optional === true; - const hasDefault = - (config as StaticInputPortConfig).default !== undefined; - return !isOptional && !hasDefault && !forceOptionalSet.has(name); - }) - .map(([name]) => name), - }; -} - -export function jsonSchemaToPortConfigMap( - ioSchema: JSONSchema4 -): PortConfigMap { - return Object.fromEntries( - Object.entries(ioSchema.properties ?? {}).map(([portName, portSchema]) => { - const config: StaticInputPortConfig | StaticOutputPortConfig = { - // Note we preserve the entire JSON schema inside the type wrapper. The - // rest of the fields have special meaning in port configs so we also - // put them at the top-level. - type: unsafeType(portSchema), - }; - if (portSchema.title !== undefined) { - config.title = portSchema.title; - } - if (portSchema.description !== undefined) { - config.description = portSchema.description; - } - if (portSchema.default !== undefined) { - (config as StaticInputPortConfig).default = portSchema.default; - } - if (portSchema.format !== undefined) { - config.format = portSchema.format as Format | undefined; - } - if (portSchema.behavior !== undefined) { - config.behavior = portSchema.behavior; - } - return [portName, config]; - }) - ); -} diff --git a/packages/build/src/internal/define/node-factory.ts b/packages/build/src/internal/define/node-factory.ts deleted file mode 100644 index 58fc730ad32..00000000000 --- a/packages/build/src/internal/define/node-factory.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { NewNodeFactory, NewNodeValue } from "@google-labs/breadboard"; -import type { Definition } from "./definition.js"; -import type { JsonSerializable } from "../type-system/type.js"; -import type { Expand } from "../common/type-util.js"; - -/* eslint-disable @typescript-eslint/ban-types */ -/* eslint-disable @typescript-eslint/no-explicit-any */ - -/** - * `NodeFactoryFromDefinition` takes a {@link NodeDefinition} type (as returned - * by {@link defineNodeType}) and produces a {@link NodeFactory} type suitable - * for use with {@link KitBuilder}. - */ -export type NodeFactoryFromDefinition< - D extends Definition, -> = - D extends Definition< - infer SI, - infer SO, - infer DI, - infer DO, - infer OI, - any, - any, - any, - any - > - ? NewNodeFactory< - Expand< - Omit & { [K in OI]?: SI[K] } & (DI extends JsonSerializable - ? { [K: string]: NewNodeValue } - : {}) - >, - Expand< - SO & - (DO extends JsonSerializable ? { [K: string]: NewNodeValue } : {}) - > - > - : never; diff --git a/packages/build/src/internal/define/unsafe-schema.ts b/packages/build/src/internal/define/unsafe-schema.ts deleted file mode 100644 index 6d503b643e1..00000000000 --- a/packages/build/src/internal/define/unsafe-schema.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { Schema } from "@google-labs/breadboard"; -import type { JSONSchema4 } from "json-schema"; - -/** - * Can be used in a node definition's `describe` function to directly specify - * some raw JSON schema, instead of a normal `@breadboard-ai/build` port - * configuration. - * - * Useful for cases like the `invoke` node where we need to trust that the - * schema returned by some dynamically loaded board is valid. - */ -export function unsafeSchema(schema: JSONSchema4 | Schema): UnsafeSchema { - return { [unsafeSchemaAccessor]: schema as JSONSchema4 }; -} - -/** Checks whether an object was created by {@link unsafeSchema}. */ -export function isUnsafeSchema(value: unknown): value is UnsafeSchema { - return ( - typeof value === "object" && value !== null && unsafeSchemaAccessor in value - ); -} - -/** The interface for {@link unsafeSchema}. */ -export interface UnsafeSchema { - [unsafeSchemaAccessor]: JSONSchema4; -} - -/** A package-private accessor for {@link unsafeSchema}. */ -export const unsafeSchemaAccessor = Symbol(); diff --git a/packages/build/src/internal/kit.ts b/packages/build/src/internal/kit.ts deleted file mode 100644 index 7d9bf84499e..00000000000 --- a/packages/build/src/internal/kit.ts +++ /dev/null @@ -1,272 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - addKit, - Board, - inspect, - type BreadboardNode, - type ConfigOrGraph, - type InputValues, - type Kit, - type KitConstructor, - type NewNodeFactory, - type NewNodeValue, - type NodeHandler, - type NodeHandlerContext, - type NodeHandlerFunction, - type NodeHandlerObject, - type NodeHandlers, -} from "@google-labs/breadboard"; -import type { - GraphDescriptor, - KitTag, - SubGraphs, -} from "@google-labs/breadboard-schema/graph.js"; -import { GraphToKitAdapter, KitBuilder } from "@google-labs/breadboard/kits"; -import type { BoardDefinition } from "./board/board.js"; -import { serialize } from "./board/serialize.js"; -import type { Expand } from "./common/type-util.js"; -import { - isDiscreteComponent, - type Definition, - type GenericDiscreteComponent, -} from "./define/definition.js"; - -type ComponentManifest = Record< - string, - GenericDiscreteComponent | BoardDefinition | GraphDescriptor ->; - -export interface KitOptions { - title: string; - description: string; - version: string; - url: string; - tags?: KitTag[]; - components: T; -} - -export type BuildKit = KitWithKnownHandlers & - KitConstructor> & - T & { legacy(): Promise>> }; - -type KitWithKnownHandlers = Kit & { - handlers: { [K in keyof T]: NodeHandlerObject }; -}; - -export async function kit( - options: KitOptions -): Promise> { - const handlers: Record = {}; - - // TODO(aomarks) Unclear why this needs to be a class, and why it needs - // certain fields on both the static and instance sides. - const kit: KitConstructor = class GeneratedBreadboardKit { - static handlers = handlers; - static url = options.url; - handlers = handlers; - title = options.title; - description = options.description; - version = options.version; - url = options.url; - tags = options.tags ?? []; - }; - - const kitBoundComponents = Object.fromEntries( - Object.entries(options.components).map(([id, component]) => [ - id, - isGraphDescriptor(component) - ? component - : bindComponentToKit(component, { kit, id }), - ]) - ); - - for (const [id, component] of Object.entries(kitBoundComponents)) { - if (isDiscreteComponent(component)) { - handlers[id] = component; - } else if (isGraphDescriptor(component)) { - handlers[id] = await makeGraphDescriptorComponentHandler(id, component); - } else { - handlers[id] = makeBoardComponentHandler(component); - } - } - - return Object.assign(kit, { - ...kitBoundComponents, - legacy: () => makeLegacyKit(options), - }) as BuildKit; -} - -function makeBoardComponentHandler(board: BoardDefinition): NodeHandler { - const serialized = serialize(board); - return { - metadata: { - ...board.metadata, - title: board.title ?? (board.metadata?.title as string | undefined), - description: - board.description ?? - (board.metadata?.description as string | undefined), - }, - describe: board.describe.bind(board), - async invoke(inputs: InputValues, context: NodeHandlerContext) { - // Assume that invoke is available, since that's part of core kit, and use - // that to execute our serialized board. - const invoke = findInvokeFunctionFromContext(context); - if (invoke === undefined) { - return { - $error: - `Could not find an "invoke" node in the given context while ` + - `trying to execute the board with id "${board.id}" as component.`, - }; - } - return invoke({ ...inputs, $board: serialized }, context); - }, - }; -} - -async function makeGraphDescriptorComponentHandler( - id: string, - descriptor: GraphDescriptor -): Promise { - const description = await inspect(descriptor).describe(); - return { - metadata: { - ...descriptor.metadata, - title: descriptor.title, - description: descriptor.description, - }, - describe: () => Promise.resolve(description), - async invoke(inputs: InputValues, context: NodeHandlerContext) { - // Assume that invoke is available, since that's part of core kit, and use - // that to execute our serialized board. - const invoke = findInvokeFunctionFromContext(context); - if (invoke === undefined) { - return { - $error: - `Could not find an "invoke" node in the given context while ` + - `trying to execute the board with id "${id}" as component.`, - }; - } - return invoke({ ...inputs, $board: descriptor }, context); - }, - }; -} - -function findInvokeFunctionFromContext( - context: NodeHandlerContext -): NodeHandlerFunction | undefined { - for (const kit of context.kits ?? []) { - const invoke = kit.handlers["invoke"]; - if (invoke !== undefined) { - return "invoke" in invoke ? invoke.invoke : invoke; - } - } - return undefined; -} - -/** - * Describes the kit that a component is bound to, along with that component's - * id within that kit. - */ -export interface KitBinding { - id: string; - kit: KitConstructor; -} - -/** - * Returns a proxy of a component instance which binds it to a kit. - */ -function bindComponentToKit< - T extends GenericDiscreteComponent | BoardDefinition, ->(definition: T, kitBinding: KitBinding): T { - return new Proxy(definition, { - apply(target, thisArg, args) { - // The instantiate functions for both discrete and board components have - // an optional final argument called `kitBinding`. Normally it is - // undefined, but when called via this proxy we will add the final - // argument. Now those instances know which kit they're from, which helps - // us serialize them. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return target.apply(thisArg, [...args, kitBinding] as any); - }, - }); -} - -/** - * We also expose a "legacy" property, an async function which returns a version - * of this Kit that can be used directly in the old API. - */ -async function makeLegacyKit({ - title, - description, - version, - url, - components, -}: KitOptions): Promise>> { - const kitBoard = new Board({ title, description, version }); - const { Core } = await import( - // Cast to prevent TypeScript from trying to import these types (we don't - // want to depend on them in the type system because it's a circular - // dependency). - "@google-labs/core-kit" as string - ); - const core = kitBoard.addKit(Core) as object as { - invoke: (config?: ConfigOrGraph) => BreadboardNode; - }; - const handlers: NodeHandlers = {}; - const adapter = await GraphToKitAdapter.create(kitBoard, url, []); - const graphs: SubGraphs = {}; - for (const [id, component] of Object.entries(components)) { - if (isDiscreteComponent(component)) { - handlers[id] = component; - } else { - core.invoke({ - $id: id, - $board: `#${id}`, - $metadata: { - ...component.metadata, - title: component.title ?? component.metadata?.title, - description: component.description ?? component.metadata?.description, - }, - }); - graphs[id] = isGraphDescriptor(component) - ? component - : serialize(component); - handlers[id] = adapter.handlerForNode(id); - } - } - kitBoard.graphs = graphs; - const builder = new KitBuilder(adapter.populateDescriptor({ url })); - return addKit(builder.build(handlers)) as object as Promise< - Expand> - >; -} - -type LegacyKit = { - [K in keyof T]: LegacyNodeSignature; -}; - -type LegacyNodeSignature< - T extends GenericDiscreteComponent | BoardDefinition | GraphDescriptor, -> = T extends - | BoardDefinition - // eslint-disable-next-line @typescript-eslint/no-explicit-any - | Definition - ? NewNodeFactory< - Expand>, - Expand> - > - : NewNodeFactory; - -function isGraphDescriptor(value: unknown): value is GraphDescriptor { - return ( - typeof value === "object" && - value !== null && - "nodes" in value && - "edges" in value - ); -} diff --git a/packages/build/src/internal/type-system/annotate.ts b/packages/build/src/internal/type-system/annotate.ts deleted file mode 100644 index 14f97c27ad8..00000000000 --- a/packages/build/src/internal/type-system/annotate.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { BehaviorSchema } from "@google-labs/breadboard"; -import { toJSONSchema, type BreadboardType } from "./type.js"; - -/** - * Add Breadboard-specific annotations to a schema. - */ -export function annotate( - value: T, - annotations: { - behavior: BehaviorSchema[]; - } -): T { - const original = toJSONSchema(value); - const behavior = [ - ...new Set([...(original.behavior ?? []), ...annotations.behavior]), - ]; - return { - jsonSchema: { - ...original, - behavior, - }, - } as BreadboardType as T; -} diff --git a/packages/build/src/internal/type-system/any-of.ts b/packages/build/src/internal/type-system/any-of.ts deleted file mode 100644 index 85132f47c8d..00000000000 --- a/packages/build/src/internal/type-system/any-of.ts +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { JSONSchema4TypeName } from "json-schema"; -import { - toJSONSchema, - type BreadboardType, - type AdvancedBreadboardType, - type ConvertBreadboardType, -} from "./type.js"; - -/** - * Make a Breadboard type that can have any of the given `members`. Equivalent - * to JSON Schema's `anyOf`, and TypeScript's union operator (`|`). - * - * @param members The types which are allowed to match. - */ -export function anyOf< - T extends [BreadboardType, BreadboardType, ...BreadboardType[]], ->(...members: T): AdvancedBreadboardType> { - const types = members.map(toJSONSchema); - const allTypesAreBasic = types.every( - (member) => - typeof member.type === "string" && Object.keys(member).length === 1 - ); - if (allTypesAreBasic) { - return { - jsonSchema: { - type: types.map((member) => member.type as JSONSchema4TypeName), - }, - }; - } - const uniqueCoreTypes = new Set(types.map(({ type }) => type)); - if (uniqueCoreTypes.size === 1) { - // TODO(aomarks) Remove this when we no longer have this limitation. - // This is a no-op according to JSON Schema, but it's helpful in Breadboard - // right now because we have some code that assumes there is always a - // top-level core "type", and doesn't understand "anyOf". In the case where - // all the "anyOf" core types are the same, we can hoist it up to make that - // code happy. - return { - jsonSchema: { - type: [...uniqueCoreTypes][0], - anyOf: types, - }, - }; - } - return { - jsonSchema: { anyOf: types }, - }; -} diff --git a/packages/build/src/internal/type-system/array.ts b/packages/build/src/internal/type-system/array.ts deleted file mode 100644 index 8dc9f80819a..00000000000 --- a/packages/build/src/internal/type-system/array.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - toJSONSchema, - type AdvancedBreadboardType, - type BreadboardType, - type ConvertBreadboardType, -} from "./type.js"; - -/** - * Creates an array type for the specified element type. - * - * @param elementType - The type of elements in the array. - * @returns An `AdvancedBreadboardType` representing an array of the specified element type. - */ -export function array( - elementType: T -): AdvancedBreadboardType[]> { - return { - jsonSchema: { - type: "array", - items: toJSONSchema(elementType), - }, - }; -} diff --git a/packages/build/src/internal/type-system/enumeration.ts b/packages/build/src/internal/type-system/enumeration.ts deleted file mode 100644 index 078938ff19b..00000000000 --- a/packages/build/src/internal/type-system/enumeration.ts +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { AdvancedBreadboardType } from "./type.js"; - -type Enumable = string | number | boolean | null; - -/** - * Creates an enum type for the specified element type. - * - * @param values The - * @returns An `AdvancedBreadboardType` representing an enumeration of the given - * values. - */ -export function enumeration( - ...values: T -): AdvancedBreadboardType { - if (values.length === 0) { - throw new Error("enumeration needs at least one value"); - } - const types = new Set<"string" | "number" | "boolean" | "null">( - values.map((value) => { - const t = typeof value; - switch (t) { - case "string": - case "number": - case "boolean": - return t; - } - if (value === null) { - return "null"; - } - throw new Error( - `enumeration values must be string, number, boolean, or null. ` + - `Got ${t}.` - ); - }) - ); - if (types.size === 1) { - return { - jsonSchema: { - type: [...types][0]!, - enum: values, - }, - }; - } - return { - jsonSchema: { - enum: values, - }, - }; -} diff --git a/packages/build/src/internal/type-system/intersect.ts b/packages/build/src/internal/type-system/intersect.ts deleted file mode 100644 index b8e88fcd5b8..00000000000 --- a/packages/build/src/internal/type-system/intersect.ts +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { type JSONSchema4 } from "json-schema"; -import { - toJSONSchema, - type AdvancedBreadboardType, - type BreadboardType, - type ConvertBreadboardType, - type JsonSerializable, -} from "./type.js"; - -type Intersectable = AdvancedBreadboardType<{ [K: string]: JsonSerializable }>; - -/** - * Intersect takes 2 or more types and returns their intersection. It uses the - * `&` operator for TypeScript, and a custom object-combiner for JSON Schema. - * - * Note the following requirements: - * - * - There must be at least 2 arguments. - * - All arguments must be JSON objects. - * - No two arguments can share a property. - * - Additional properties must be set to true or false, but otherwise not - * constrained. - */ -export function intersect< - T extends [Intersectable, Intersectable, ...Intersectable[]], ->(...members: T): AdvancedBreadboardType> { - // TODO(aomarks) This function is somewhat limited. We can likely use JSON - // Schema's `allOf` to support more cases, but we need to be very careful - // about the semantics of "additionalProperties". - if (members.length < 2) { - throw new Error( - `intersect requires at least 2 arguments, got ${members.length}` - ); - } - const properties: Record = {}; - let additionalProperties = false; - const required = new Set(); - for (const member of members) { - const converted = toJSONSchema(member); - if (converted.type !== "object") { - throw new Error(`intersect only supports objects, got ${converted.type}`); - } - if (converted.properties !== undefined) { - for (const [name, schema] of Object.entries(converted.properties)) { - if (properties[name]) { - throw new Error( - `intersect only supports disjoint properties, ` + - `got "${name}" 2 or more times` - ); - } - properties[name] = schema; - } - } - if (converted.required !== undefined) { - for (const name of converted.required as string[]) { - required.add(name); - } - } - if (converted.additionalProperties === true) { - additionalProperties = true; - } else if (converted.additionalProperties) { - throw new Error( - `intersect only supports closed or fully open objects, got ` + - JSON.stringify({ - additionalProperties: converted.additionalProperties, - }) - ); - } - } - return { - jsonSchema: { - type: "object", - properties, - required: [...required], - additionalProperties, - }, - }; -} - -export type IntersectArrayMembersRecursively = - ALL extends [ - infer ITEM extends BreadboardType, - ...infer REST extends BreadboardType[], - ] - ? ConvertBreadboardType & IntersectArrayMembersRecursively - : unknown; diff --git a/packages/build/src/internal/type-system/json-schema.ts b/packages/build/src/internal/type-system/json-schema.ts deleted file mode 100644 index 44366ca824e..00000000000 --- a/packages/build/src/internal/type-system/json-schema.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { type Schema } from "@google-labs/breadboard"; -import { unsafeType } from "./unsafe.js"; - -/** - * The Breadboard Type Expression for JSON Schema itself. Use this when you need - * to declare an input or output port whose type is itself a JSON Schema object. - */ -export const jsonSchema = unsafeType( - // TODO(aomarks) Replace with the official JSONSchema7 type and - // { $ref: "https://json-schema.org/draft-07/schema#" }. But we first need to - // support $ref schemas more broadly, and possibly align our Schema vs - // JSONSchema7 types. - { - type: "object", - behavior: ["json-schema"], - properties: {}, - required: [], - additionalProperties: true, - } -); diff --git a/packages/build/src/internal/type-system/object.ts b/packages/build/src/internal/type-system/object.ts deleted file mode 100644 index 12e1acbc8fb..00000000000 --- a/packages/build/src/internal/type-system/object.ts +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { JSONSchema4 } from "json-schema"; -import type { Expand } from "../common/type-util.js"; -import { - toJSONSchema, - type AdvancedBreadboardType, - type BreadboardType, - type ConvertBreadboardType, - type JsonSerializable, -} from "./type.js"; - -export function object< - T extends Record, ->( - properties: T -): AdvancedBreadboardType< - keyof T extends never - ? object & JsonSerializable - : Expand< - { - [P in keyof T as T[P] extends BreadboardType - ? P - : never]: T[P] extends BreadboardType - ? ConvertBreadboardType - : never; - } & { - [P in keyof T as T[P] extends OptionalProperty - ? P - : never]?: T[P] extends OptionalProperty - ? ConvertBreadboardType - : never; - } - > ->; - -export function object< - T extends Record, - A extends BreadboardType, ->( - properties: T, - additional: A -): AdvancedBreadboardType< - Expand< - { [x: string]: ConvertBreadboardType } & { - [P in keyof T as T[P] extends BreadboardType - ? P - : never]: T[P] extends BreadboardType - ? ConvertBreadboardType - : never; - } & { - [P in keyof T as T[P] extends OptionalProperty - ? P - : never]?: T[P] extends OptionalProperty - ? ConvertBreadboardType - : never; - } - > ->; - -/** - * Make a Breadboard type for an object. - * - * @param properties Object mapping from property name to Breadboard Type. Wrap - * the Breadboard Type with {@link optional} to make the property optional. - * @param additional A Breadboard Type that is allowed for additional properties - * (meaning ones not listed in {@link properties}). If ommitted, no additional - * properties are allowed. - */ -export function object( - properties: Record, - additional?: BreadboardType -): AdvancedBreadboardType { - const jsonSchema: JSONSchema4 = { - type: "object", - properties: Object.fromEntries( - Object.entries(properties).map(([name, type]) => [ - name, - toJSONSchema(isOptional(type) ? type.type : type), - ]) - ), - }; - jsonSchema.required = Object.entries(properties) - .filter(([_, type]) => !isOptional(type)) - .map(([name]) => name); - if (additional === undefined) { - jsonSchema.additionalProperties = false; - } else if (additional === "unknown") { - jsonSchema.additionalProperties = true; - } else { - jsonSchema.additionalProperties = toJSONSchema(additional); - } - return { jsonSchema }; -} - -/** - * Wraps a type to indicate that a property is optional in the context of - * declaring an {@link object} type. - */ -export function optional( - propertyType: T -): OptionalProperty { - return { __isOptionalProperty: true, type: propertyType }; -} - -interface OptionalProperty { - __isOptionalProperty: true; - type: T; -} - -function isOptional( - value: T | OptionalProperty -): value is OptionalProperty { - return (value as Partial>).__isOptionalProperty === true; -} diff --git a/packages/build/src/internal/type-system/string.ts b/packages/build/src/internal/type-system/string.ts deleted file mode 100644 index 4226c530107..00000000000 --- a/packages/build/src/internal/type-system/string.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { AdvancedBreadboardType } from "./type.js"; - -/** - * JSON Schema options for strings. - */ -export interface StringOptions { - /** https://json-schema.org/understanding-json-schema/reference/string#format */ - format?: string; - /** https://json-schema.org/understanding-json-schema/reference/string#regexp */ - pattern?: string; - /** https://json-schema.org/understanding-json-schema/reference/string#length */ - minLength?: number; - /** https://json-schema.org/understanding-json-schema/reference/string#length */ - maxLength?: number; -} - -/** - * Create a string type with additional options. - */ -export function string(options: StringOptions): AdvancedBreadboardType { - return { jsonSchema: { type: "string", ...options } }; -} diff --git a/packages/build/src/internal/type-system/type.ts b/packages/build/src/internal/type-system/type.ts deleted file mode 100644 index a40a67dcd5c..00000000000 --- a/packages/build/src/internal/type-system/type.ts +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { JSONSchema4 } from "json-schema"; - -/** - * A `BreadboardType` is an object that can be serialized to JSON Schema for - * runtime, and also carries a matching TypeScript type for compile time. - */ -export type BreadboardType = - | BasicBreadboardType - | AdvancedBreadboardType; - -/** - * The basic Breadboard types that can be written directly. - */ -export type BasicBreadboardType = - | "string" - | "number" - | "boolean" - | "null" - | "unknown"; - -/** - * All Breadboard values must be JSON serializable, and this is the set of - * JSON serializable types. - */ -export type JsonSerializable = - | string - | number - | boolean - | null - | Array - | { [K: string]: JsonSerializable }; - -/** - * A type that's more complicated than a {@link BasicBreadboardType}. Directly - * owns a TypeScript type for compile time, and a JSON schema for run time. - */ -export interface AdvancedBreadboardType< - // We only need to hold onto this type parameter so that we can infer it - // later. - // - // eslint-disable-next-line @typescript-eslint/no-unused-vars - T extends JsonSerializable, -> { - readonly jsonSchema: JSONSchema4; -} - -/** - * Convert from {@link BreadboardType} to TypeScript type. - */ -export type ConvertBreadboardType = - BT extends "string" - ? string - : BT extends "number" - ? number - : BT extends "boolean" - ? boolean - : BT extends "null" - ? null - : BT extends "unknown" - ? JsonSerializable - : BT extends AdvancedBreadboardType - ? TT - : never; - -/** - * Convert a {@link BreadboardType} to JSON Schema. - */ -export function toJSONSchema(type: BreadboardType): JSONSchema4 { - if (typeof type === "object" && "jsonSchema" in type) { - // Make a copy because it's not uncommon for callers to mutate this object, - // (e.g. adding a description to a port schema), and 2 ports might share an - // advanced breadboard type instance (e.g. dynamic ports). - return structuredClone(type.jsonSchema); - } - switch (type) { - case "string": - case "number": - case "boolean": - case "null": { - return { type }; - } - case "unknown": { - // All possible JSON schema data types. - // - // We could return {} here, but returning all possible types is a bit more - // explicit. Also, there is some other Breadboard code which assumes when - // there is no type, that the type is string (this is a bug, since no type - // actually means anything). - return { - type: ["array", "boolean", "null", "number", "object", "string"], - }; - } - default: { - throw new Error( - `Unknown BreadboardType: <${typeof type}> ${type satisfies never}` - ); - } - } -} diff --git a/packages/build/src/internal/type-system/unsafe.ts b/packages/build/src/internal/type-system/unsafe.ts deleted file mode 100644 index 8ed8ba5f282..00000000000 --- a/packages/build/src/internal/type-system/unsafe.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { JSONSchema4 } from "json-schema"; -import type { AdvancedBreadboardType, JsonSerializable } from "./type.js"; - -/** - * If none of the included type utilities are able to express both the required - * JSON Schema and its corresponding TypeScript type you need, then `unsafeType` - * can be used to manually create a type that directly specifies both. - * - * This function is called `unsafeType` because there is no guarantee that the - * JSON Schema and TypeScript types you specify are actually equivalent, hence - * it must be used with care. Prefer using one of the provided types if - * possible, and consider filing a feature request if you think a type should be - * natively supported. - * - * Example: - * - * ```ts - * import {unsafeType} from "@breadboard-ai/build"; - * - * const myCrazyType = unsafeType<{foo: string}>({ - * type: "object", - * properties: { - * foo: { - * type: "string" - * } - * }, - * required: ["foo"] - * }); - * ``` - * - * @param jsonSchema The JSON schema that will always be returned when a port - * has this type. - * @returns A `BreadboardType` which carries both the TypeScript type provided - * via the `T` generic parameter, and the corresponding JSON schema. - */ -export function unsafeType( - jsonSchema: JSONSchema4 -): AdvancedBreadboardType { - return { jsonSchema }; -} diff --git a/packages/build/src/test/better-board_test.ts b/packages/build/src/test/better-board_test.ts deleted file mode 100644 index d90320d811d..00000000000 --- a/packages/build/src/test/better-board_test.ts +++ /dev/null @@ -1,428 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test, { describe } from "node:test"; -import { board, inputNode, outputNode } from "../internal/board/board.js"; -import { converge, type Convergence } from "../internal/board/converge.js"; -import { - input, - type Input, - type InputWithDefault, -} from "../internal/board/input.js"; -import { loopback, type Loopback } from "../internal/board/loopback.js"; -import { output, type Output } from "../internal/board/output.js"; -import type { - OutputPort, - OutputPortReference, -} from "../internal/common/port.js"; -import type { Value } from "../internal/common/value.js"; - -/* eslint-disable @typescript-eslint/ban-ts-comment */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - -// TODO(aomarks) board definitions that take boards (we have this working for -// discrete component, but not boards). - -describe("input types", () => { - test("required", () => { - const foo = input(); - // $ExpectType BoardDefinition<{ foo: string; }, {}> - board({ inputs: { foo }, outputs: {} }); - }); - - test("optional", () => { - const foo = input({ optional: true }); - // $ExpectType BoardDefinition<{ foo?: string | undefined; }, {}> - board({ inputs: { foo }, outputs: {} }); - }); - - test("with default", () => { - const foo = input({ default: "foo" }); - // $ExpectType BoardDefinition<{ foo?: string | undefined; }, {}> - board({ inputs: { foo }, outputs: {} }); - }); - - test("multiple", () => { - const foo = input(); - const bar = input({ type: "number" }); - const baz = input({ type: "boolean", default: true }); - const qux = input({ optional: true }); - - // $ExpectType BoardDefinition<{ foo: string; }, {}> - board({ inputs: [inputNode({ foo })], outputs: {} }); - - // $ExpectType BoardDefinition<{ foo: string; } | { bar: number; }, {}> - board({ inputs: [inputNode({ foo }), inputNode({ bar })], outputs: {} }); - - // $ExpectType BoardDefinition<{ foo: string; bar: number; } | { bar: number; }, {}> - board({ - inputs: [inputNode({ foo, bar }), inputNode({ bar })], - outputs: {}, - }); - - // $ExpectType BoardDefinition<{ baz?: boolean | undefined; }, {}> - board({ inputs: [inputNode({ baz })], outputs: {} }); - - // $ExpectType BoardDefinition<{ qux?: string | undefined; }, {}> - board({ inputs: [inputNode({ qux })], outputs: {} }); - }); -}); - -describe("output types", () => { - test("output port", () => { - const foo = {} as OutputPort; - // $ExpectType BoardDefinition<{}, { foo: string; }> - board({ inputs: {}, outputs: { foo } }); - }); - - test("output port reference", () => { - const foo = {} as OutputPortReference; - // $ExpectType BoardDefinition<{}, { foo: string; }> - board({ inputs: {}, outputs: { foo } }); - }); - - test("input", () => { - const foo = input(); - // $ExpectType BoardDefinition<{}, { foo: string; }> - board({ inputs: {}, outputs: { foo } }); - }); - - test("optional input", () => { - const foo = input({ optional: true }); - // $ExpectType BoardDefinition<{}, { foo?: string | undefined; }> - board({ inputs: {}, outputs: { foo } }); - }); - - test("input with default", () => { - const foo = input({ optional: true }); - // $ExpectType BoardDefinition<{}, { foo?: string | undefined; }> - board({ inputs: {}, outputs: { foo } }); - }); - - test("loopback", () => { - const foo = loopback(); - // $ExpectType BoardDefinition<{}, { foo: string; }> - board({ inputs: {}, outputs: { foo } }); - }); - - test("convergence", () => { - const foo = converge(input(), input()); - // $ExpectType BoardDefinition<{}, { foo: string; }> - board({ inputs: {}, outputs: { foo } }); - }); - - test("multiple", () => { - const foo = input(); - const bar = input({ type: "number" }); - const baz = input({ type: "boolean", default: true }); - const qux = input({ optional: true }); - - // $ExpectType BoardDefinition<{}, { foo: string; }> - board({ inputs: {}, outputs: [outputNode({ foo })] }); - - // $ExpectType BoardDefinition<{}, { baz?: boolean | undefined; }> - board({ inputs: {}, outputs: [outputNode({ baz })] }); - - // $ExpectType BoardDefinition<{}, { qux?: string | undefined; }> - board({ inputs: {}, outputs: [outputNode({ qux })] }); - - // $ExpectType BoardDefinition<{}, { foo: string; bar: number; } | { foo: string; }> - const b = board({ - inputs: {}, - outputs: [outputNode({ foo, bar }), outputNode({ foo })], - }); - - // $ExpectType { foo: Value; bar: Value; } - b({}).outputs; - - // $ExpectType BoardDefinition<{}, { baz?: boolean | undefined; }> - board({ inputs: {}, outputs: [outputNode({ baz })] }); - - // $ExpectType BoardDefinition<{}, { qux?: string | undefined; }> - board({ inputs: {}, outputs: [outputNode({ qux })] }); - }); -}); - -describe("instantiate function", () => { - describe("monomorphic", () => { - const foo = input(); - const bar = input({ type: "number", optional: true }); - // $ExpectType BoardDefinition<{ bar?: number | undefined; foo: string; }, { bar?: number | undefined; foo: string; }> - const b = board({ inputs: { foo, bar }, outputs: { foo, bar } }); - // $ExpectType { bar?: Value; foo: Value; } & { $id?: string | undefined; $metadata?: NodeMetadata | undefined; } - const x = {} as Parameters[0]; - - test("instance types", () => { - // $ExpectType BoardInstance<{ bar?: number | undefined; foo: string; }, { bar?: number | undefined; foo: string; }> - const inst = b({ foo: "foo", bar: 123 }); - - // $ExpectType { bar?: Value; foo: Value; } - inst.outputs; - }); - - test("required values", () => { - b({ foo: "foo" }); - b( - // @ts-expect-error - { bar: 123 } - ); - // @ts-expect-error - b(); - b( - // @ts-expect-error - {} - ); - }); - - test("raw value", () => { - b({ - foo: "foo", - bar: 123, - }); - - b({ - // @ts-expect-error - foo: 123, - // @ts-expect-error - bar: "bar", - }); - }); - - test("output port", () => { - b({ - foo: {} as OutputPort, - bar: {} as OutputPort, - }); - - b({ - // @ts-expect-error - foo: {} as OutputPort, - // @ts-expect-error - bar: {} as OutputPort, - }); - }); - - test("output port reference", () => { - b({ - foo: {} as OutputPortReference, - bar: {} as OutputPortReference, - }); - - b({ - // @ts-expect-error - foo: {} as OutputPortReference, - // @ts-expect-error - bar: {} as OutputPortReference, - }); - }); - - test("input", () => { - b({ - foo: input(), - bar: input({ type: "number" }), - }); - - b({ - // @ts-expect-error - foo: input({ type: "number" }), - // @ts-expect-error - bar: input(), - }); - }); - - test("optional input", () => { - b({ - // @ts-expect-error - foo: input({ optional: true }), - bar: input({ type: "number", optional: true }), - }); - }); - - test("input with default", () => { - b({ - foo: input({ default: "foo" }), - bar: input({ type: "number", default: 123 }), - }); - }); - - test("loopback", () => { - b({ - foo: loopback(), - bar: loopback({ type: "number" }), - }); - - b({ - // @ts-expect-error - foo: loopback({ type: "number" }), - // @ts-expect-error - bar: loopback(), - }); - }); - - test("convergence", () => { - b({ - foo: converge(input(), input()), - bar: converge(input({ type: "number" }), input({ type: "number" })), - }); - b({ - // @ts-expect-error - foo: converge(input({ type: "number" }), input({ type: "number" })), - // @ts-expect-error - bar: converge(input(), input()), - }); - }); - }); - - test("polymorphic", () => { - const foo = input(); - const bar = input({ type: "number" }); - // $ExpectType BoardDefinition<{ foo: string; } | { bar: number; }, {}> - const b = board({ - inputs: [inputNode({ foo }), inputNode({ bar })], - outputs: {}, - }); - // $ExpectType ({ foo: Value; } | { bar: Value; }) & { $id?: string | undefined; $metadata?: NodeMetadata | undefined; } - const x = {} as Parameters[0]; - - test("instantiate function types", () => { - // @ts-expect-error - b(); - b( - // @ts-expect-error - {} - ); - b({ foo: "foo" }); - b({ bar: 123 }); - b({ - foo: "foo", - // @ts-expect-error - xxx: 123, - }); - b({ - // @ts-expect-error - foo: 123, - }); - b({ - // @ts-expect-error - bar: "bar", - }); - }); - }); -}); - -test("board metadata", () => { - const foo = input(); - // $ExpectType BoardDefinition<{ foo: string; }, {}> - board({ - id: "my-id", - title: "My Title", - description: "My Description", - version: "1.0.0", - metadata: {}, - - inputs: { foo }, - outputs: {}, - }); -}); - -test("one input node metadata", () => { - const foo = input(); - // $ExpectType BoardDefinition<{ foo: string; }, {}> - board({ - inputs: inputNode( - { foo }, - { - id: "input-node-id", - description: "Input Node Description", - } - ), - outputs: {}, - }); -}); - -test("one output node metadata", () => { - const foo = input({ type: "boolean" }); - // $ExpectType BoardDefinition<{}, { foo: boolean; }> - board({ - inputs: {}, - outputs: outputNode( - { foo }, - { - id: "output-node-id", - description: "Output Node Description", - } - ), - }); -}); - -test("output port metadata", () => { - const foo = input(); - const bar = input({ type: "number" }); - // $ExpectType BoardDefinition<{}, { foo: string; bar: number; }> - board({ - inputs: {}, - outputs: { - foo: output(foo, { - id: "foo-port-id", - description: "Foo Port Description", - }), - bar: output(bar, { - id: "bar-port-id", - description: "Bar Port Description", - }), - }, - }); -}); - -describe("exotic output types", () => { - // $ExpectType BoardDefinition<{}, { foo: number | boolean; }> - board({ - inputs: {}, - outputs: { foo: {} as Loopback }, - }); - - // $ExpectType BoardDefinition<{}, { foo: number | boolean; }> - board({ - inputs: {}, - outputs: { foo: {} as Convergence }, - }); - - // $ExpectType BoardDefinition<{}, { foo: number | boolean; }> - board({ - inputs: {}, - outputs: { foo: {} as Output }, - }); - - // $ExpectType BoardDefinition<{}, { foo: number | boolean; }> - board({ - inputs: {}, - outputs: { foo: {} as OutputPort }, - }); - - // $ExpectType BoardDefinition<{}, { foo: number | boolean; }> - board({ - inputs: {}, - outputs: { foo: {} as OutputPortReference }, - }); - - // $ExpectType BoardDefinition<{}, { foo: number | boolean; }> - board({ - inputs: {}, - outputs: { foo: {} as Input }, - }); - - // $ExpectType BoardDefinition<{}, { foo?: number | boolean | undefined; }> - board({ - inputs: {}, - outputs: { foo: {} as InputWithDefault }, - }); - - // $ExpectType BoardDefinition<{}, { foo: number | boolean; }> - board({ - inputs: {}, - outputs: { foo: {} as Value }, - }); -}); diff --git a/packages/build/src/test/board_test.ts b/packages/build/src/test/board_test.ts deleted file mode 100644 index c874d0194f0..00000000000 --- a/packages/build/src/test/board_test.ts +++ /dev/null @@ -1,307 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -import { defineNodeType, input, output } from "@breadboard-ai/build"; -import { test } from "node:test"; -import { board, inputNode, outputNode } from "../internal/board/board.js"; -import assert from "node:assert/strict"; - -const inStr = input(); -const inNum = input({ type: "number" }); - -const testNode = defineNodeType({ - name: "example", - inputs: { - inStr: { - type: "string", - }, - inNum: { - type: "number", - }, - }, - outputs: { - outNum: { - type: "number", - }, - outStr: { - type: "string", - }, - }, - invoke: () => { - return { - outNum: 123, - outStr: "foo", - }; - }, -})({ inStr, inNum }); -const { outNum, outStr } = testNode.outputs; - -test("expect type: 0 in, 0 out", () => { - // $ExpectType BoardDefinition<{}, {}> - const definition = board({ inputs: {}, outputs: {} }); - // $ExpectType BoardInstance<{}, {}> - definition({}); - // $ExpectType BoardInstance<{}, {}> - const instance = definition({}); - // $ExpectType {} - instance.outputs; -}); - -test("expect type: 1 in, 1 out", () => { - // $ExpectType BoardDefinition<{ inStr: string; }, { outNum: number; }> - const definition = board({ inputs: { inStr }, outputs: { outNum } }); - // NodeInstance; }>, BoardPortConfig<{ outNum: OutputPort<{ type: "boolean"; }>; }>> - const instance = definition({ inStr: "inStr" }); - // $ExpectType { outNum: Value; } - instance.outputs; - // $ExpectType Value - instance.outputs.outNum; -}); - -test("expect type: nested boards", () => { - const defA = board({ inputs: { inNum }, outputs: { outStr } }); - const defB = board({ inputs: { inStr }, outputs: { outNum } }); - const instanceA = defA({ inNum: 123 }); - // $ExpectType BoardInstance<{ inStr: string; }, { outNum: number; }> - const instanceB = defB({ inStr: instanceA.outputs.outStr }); - // $ExpectType { outNum: Value; } - instanceB.outputs; - // $ExpectType Value - instanceB.outputs.outNum; -}); - -test("expect type error: missing instantiate param", () => { - const definition = board({ inputs: { inStr, inNum }, outputs: { outNum } }); - // @ts-expect-error missing both - definition(); - // @ts-expect-error missing both - definition({}); - // @ts-expect-error missing inStr - definition({ inNum: 123 }); - // @ts-expect-error missing inNum - definition({ inStr: "inStr" }); -}); - -test("expect type error: board input/output types", () => { - const noPrimary = defineNodeType({ - name: "noPrimary", - inputs: { - in: { type: "string" }, - }, - outputs: { - out: { type: "string" }, - }, - invoke: () => ({ out: "foo" }), - }); - - board({ - // @ts-expect-error - inputs: { - in1: undefined, - in2: null, - in3: "foo", - in4: noPrimary({ in: "foo" }), - }, - // @ts-expect-error - outputs: { - out1: undefined, - out2: null, - out3: "foo", - out4: noPrimary({ in: "foo" }), - }, - }); -}); - -test("expect type error: incorrect make instance param type", () => { - const definition = board({ inputs: { inStr, inNum }, outputs: {} }); - definition({ - inStr: "foo", - // @ts-expect-error inNum should be number, not string - inNum: "123", - }); -}); - -test("allow setting title, description, version", () => { - // $ExpectType BoardDefinition<{ inStr: string; }, { outNum: number; }> - board({ - title: "My Title", - description: "My Description", - version: "1.0.0", - inputs: { inStr }, - outputs: { outNum }, - }); -}); - -{ - const boardA = board({ inputs: {}, outputs: { outNum, outStr } }); - const boardB = board({ inputs: { inStr, inNum }, outputs: {} }); - const instanceA = boardA({}); - const instanceB = boardB({ inStr: "foo", inNum: 123 }); - - test("can instantiate node with concrete values", () => { - boardB({ - inStr: "foo", - inNum: 123, - }); - }); - - test("can instantiate node with output ports", () => { - boardB({ - inStr: instanceA.outputs.outStr, - inNum: instanceA.outputs.outNum, - }); - }); - - test("can instantiate node with mix of concrete values and output ports", () => { - boardB({ - inStr: "foo", - inNum: instanceA.outputs.outNum, - }); - boardB({ - inStr: instanceA.outputs.outStr, - inNum: 123, - }); - }); - - test("expect error: instantiate with incorrectlty typed concrete value", () => { - boardB({ - // @ts-expect-error Expect string, got number - inStr: 123, - inNum: 123, - }); - boardB({ - inStr: "foo", - // @ts-expect-error Expect number, got string - inNum: "123", - }); - }); - - test("expect error: instantiate with incorrectly typed output port", () => { - boardB({ - // @ts-expect-error Expect string, got number - inStr: instanceA.outputs.outNum, - inNum: instanceA.outputs.outNum, - }); - boardB({ - inStr: instanceA.outputs.outStr, - // @ts-expect-error Expect number, got string - inNum: instanceA.outputs.outStr, - }); - }); - - test("expect error: wrong kind of port", () => { - boardB({ - // @ts-expect-error Expect OutputPort, got InputPort - inStr: instanceB.inputs.inStr, - // @ts-expect-error Expect OutputPort, got InputPort - inNum: instanceB.inputs.inNum, - }); - }); -} - -test("describe board", async () => { - const inFoo = input({ - title: "Foo title", - description: "Foo description", - default: "Foo default", - examples: ["Foo example 1", "Foo example 2"], - }); - const boardA = board({ - inputs: { inFoo }, - outputs: { - outNum, - outStr: output(outStr, { - description: "outStr description", - title: "outStr title", - }), - }, - }); - const description = await boardA.describe(); - assert.deepEqual(description, { - inputSchema: { - type: "object", - required: [], - additionalProperties: false, - properties: { - inFoo: { - type: "string", - title: "Foo title", - description: "Foo description", - default: "Foo default", - examples: ["Foo example 1", "Foo example 2"], - }, - }, - }, - outputSchema: { - type: "object", - required: ["outNum", "outStr"], - additionalProperties: false, - properties: { - outNum: { - type: "number", - }, - outStr: { - type: "string", - title: "outStr title", - description: "outStr description", - }, - }, - }, - }); -}); - -test("polymorphic describe", async () => { - const str = input(); - const num = input({ type: "number" }); - const bool = input({ type: "boolean" }); - const testBoard = board({ - inputs: [ - inputNode({ foo: str, bar: num }, { id: "in1" }), - inputNode({ foo: str, bar: bool, baz: num }), - ], - outputs: [ - outputNode({ foo: num, bar: bool }, { id: "out1" }), - outputNode({ foo: num, bar: str, baz: bool }), - ], - }); - const description = await testBoard.describe(); - assert.deepEqual(description, { - inputSchema: { - type: "object", - properties: { - foo: { - type: "string", - }, - bar: { - type: ["number", "boolean"], - }, - baz: { - type: "number", - }, - }, - required: ["foo", "bar"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - foo: { - type: "number", - }, - bar: { - type: ["boolean", "string"], - }, - baz: { - type: "boolean", - }, - }, - required: ["foo", "bar"], - additionalProperties: false, - }, - }); -}); diff --git a/packages/build/src/test/composition_test.ts b/packages/build/src/test/composition_test.ts deleted file mode 100644 index 3f4a00865f8..00000000000 --- a/packages/build/src/test/composition_test.ts +++ /dev/null @@ -1,459 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { board } from "../internal/board/board.js"; -import { input } from "../internal/board/input.js"; -import { serialize } from "../internal/board/serialize.js"; -import { defineNodeType } from "../internal/define/define.js"; -import { output } from "../internal/board/output.js"; - -const trivialNode = defineNodeType({ - name: "trivial", - inputs: { - trivialStrIn: { type: "string" }, - trivialNumIn: { type: "number" }, - }, - outputs: { trivialOut: { type: "string" } }, - invoke: ({ trivialStrIn, trivialNumIn }) => ({ - trivialOut: `${trivialStrIn}:${trivialNumIn}`, - }), -}); - -test("can invoke one board in another", () => { - const innerStrInput = input({ description: "innerStrInput" }); - const innerNumInput = input({ type: "number", description: "innerNumInput" }); - const innerNode = trivialNode({ - trivialStrIn: innerStrInput, - trivialNumIn: innerNumInput, - }); - const innerOutput = innerNode.outputs.trivialOut; - const innerBoard = board({ - inputs: { innerStrInput, innerNumInput }, - outputs: { innerOutput }, - }); - - const outerInput = input({ description: "outerInput" }); - const nestedBoard = innerBoard({ - innerStrInput: outerInput, - innerNumInput: 42, - }); - const outerOutput = nestedBoard.outputs.innerOutput; - const outerBoard = board({ - inputs: { outerInput }, - outputs: { outerOutput }, - }); - - const serialized = serialize(outerBoard); - assert.deepEqual(serialized, { - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - outerInput: { type: "string", description: "outerInput" }, - }, - required: ["outerInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - required: ["outerOutput"], - properties: { - outerOutput: { - type: "string", - }, - }, - }, - }, - }, - { - id: "invoke-0", - type: "invoke", - configuration: { - $board: "#subgraph-0", - innerNumInput: 42, - }, - }, - ], - edges: [ - { - from: "input-0", - out: "outerInput", - to: "invoke-0", - in: "innerStrInput", - }, - { - from: "invoke-0", - out: "innerOutput", - to: "output-0", - in: "outerOutput", - }, - ], - graphs: { - "subgraph-0": { - edges: [ - { - from: "input-0", - in: "trivialNumIn", - out: "innerNumInput", - to: "trivial-0", - }, - { - from: "input-0", - out: "innerStrInput", - to: "trivial-0", - in: "trivialStrIn", - }, - { - from: "trivial-0", - out: "trivialOut", - to: "output-0", - in: "innerOutput", - }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - innerStrInput: { - type: "string", - description: "innerStrInput", - }, - innerNumInput: { - type: "number", - description: "innerNumInput", - }, - }, - required: ["innerNumInput", "innerStrInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { innerOutput: { type: "string" } }, - required: ["innerOutput"], - }, - }, - }, - { id: "trivial-0", type: "trivial", configuration: {} }, - ], - }, - }, - }); -}); - -test("can invoke one board in another (output wrappers)", () => { - const innerStrInput = input({ description: "innerStrInput" }); - const innerNumInput = input({ type: "number", description: "innerNumInput" }); - const innerNode = trivialNode({ - trivialStrIn: innerStrInput, - trivialNumIn: innerNumInput, - }); - const innerOutput = innerNode.outputs.trivialOut; - const innerBoard = board({ - inputs: { innerStrInput, innerNumInput }, - outputs: { - innerOutput: output(innerOutput, { description: "innerOutput" }), - }, - }); - - const outerInput = input({ description: "outerInput" }); - const nestedBoard = innerBoard({ - innerStrInput: outerInput, - innerNumInput: 42, - }); - const outerOutput = nestedBoard.outputs.innerOutput; - const outerBoard = board({ - inputs: { outerInput }, - outputs: { - outerOutput: output(outerOutput, { description: "outerOutput" }), - }, - }); - - const serialized = serialize(outerBoard); - assert.deepEqual(serialized, { - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - outerInput: { - type: "string", - description: "outerInput", - }, - }, - required: ["outerInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - required: ["outerOutput"], - properties: { - outerOutput: { - type: "string", - description: "outerOutput", - }, - }, - }, - }, - }, - { - id: "invoke-0", - type: "invoke", - configuration: { - $board: "#subgraph-0", - innerNumInput: 42, - }, - }, - ], - edges: [ - { - from: "input-0", - out: "outerInput", - to: "invoke-0", - in: "innerStrInput", - }, - { - from: "invoke-0", - out: "innerOutput", - to: "output-0", - in: "outerOutput", - }, - ], - graphs: { - "subgraph-0": { - edges: [ - { - from: "input-0", - in: "trivialNumIn", - out: "innerNumInput", - to: "trivial-0", - }, - { - from: "input-0", - out: "innerStrInput", - to: "trivial-0", - in: "trivialStrIn", - }, - { - from: "trivial-0", - out: "trivialOut", - to: "output-0", - in: "innerOutput", - }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - innerStrInput: { - type: "string", - description: "innerStrInput", - }, - innerNumInput: { - type: "number", - description: "innerNumInput", - }, - }, - required: ["innerNumInput", "innerStrInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - innerOutput: { - type: "string", - description: "innerOutput", - }, - }, - required: ["innerOutput"], - }, - }, - }, - { id: "trivial-0", type: "trivial", configuration: {} }, - ], - }, - }, - }); -}); - -test("can invoke one board in another (indirect)", () => { - const innerStrInput = input({ description: "innerStrInput" }); - const innerNumInput = input({ type: "number", description: "innerNumInput" }); - const innerNode = trivialNode({ - trivialStrIn: innerStrInput, - trivialNumIn: innerNumInput, - }); - const innerOutput = innerNode.outputs.trivialOut; - const innerBoard = board({ - inputs: { innerStrInput, innerNumInput }, - outputs: { innerOutput }, - }); - - const outerInput = input({ description: "outerInput" }); - const nestedBoard = innerBoard({ - innerStrInput: outerInput, - innerNumInput: 42, - }); - const outerNode = trivialNode({ - trivialStrIn: nestedBoard.outputs.innerOutput, - trivialNumIn: 47, - }); - const outerOutput = outerNode.outputs.trivialOut; - const outerBoard = board({ - inputs: { outerInput }, - outputs: { outerOutput }, - }); - - const serialized = serialize(outerBoard); - assert.deepEqual(serialized, { - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - outerInput: { type: "string", description: "outerInput" }, - }, - required: ["outerInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { outerOutput: { type: "string" } }, - required: ["outerOutput"], - }, - }, - }, - { - id: "invoke-0", - type: "invoke", - configuration: { $board: "#subgraph-0", innerNumInput: 42 }, - }, - { id: "trivial-0", type: "trivial", configuration: { trivialNumIn: 47 } }, - ], - edges: [ - { - from: "input-0", - to: "invoke-0", - out: "outerInput", - in: "innerStrInput", - }, - { - from: "invoke-0", - to: "trivial-0", - out: "innerOutput", - in: "trivialStrIn", - }, - { - from: "trivial-0", - to: "output-0", - out: "trivialOut", - in: "outerOutput", - }, - ], - graphs: { - "subgraph-0": { - edges: [ - { - from: "input-0", - to: "trivial-0", - out: "innerNumInput", - in: "trivialNumIn", - }, - { - from: "input-0", - to: "trivial-0", - out: "innerStrInput", - in: "trivialStrIn", - }, - { - from: "trivial-0", - to: "output-0", - out: "trivialOut", - in: "innerOutput", - }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - innerNumInput: { - type: "number", - description: "innerNumInput", - }, - innerStrInput: { - type: "string", - description: "innerStrInput", - }, - }, - required: ["innerNumInput", "innerStrInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { innerOutput: { type: "string" } }, - required: ["innerOutput"], - }, - }, - }, - { id: "trivial-0", type: "trivial", configuration: {} }, - ], - }, - }, - }); -}); diff --git a/packages/build/src/test/constant_test.ts b/packages/build/src/test/constant_test.ts deleted file mode 100644 index 96f0ba5620f..00000000000 --- a/packages/build/src/test/constant_test.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { test } from "node:test"; -import { input } from "../internal/board/input.js"; -import { constant } from "../internal/board/constant.js"; -import { enumeration } from "../internal/type-system/enumeration.js"; -import { anyOf } from "../internal/type-system/any-of.js"; -import { array } from "../internal/type-system/array.js"; -import { object } from "../internal/type-system/object.js"; - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -test("constant preserves types", () => { - // $ExpectType Input - constant(input()); - // $ExpectType Input<"foo" | "bar"> - constant(input({ type: enumeration("foo", "bar") })); - // $ExpectType InputWithDefault - constant( - input({ - type: anyOf("number", array(object({ foo: "number" }, "boolean"))), - default: 32, - }) - ); -}); diff --git a/packages/build/src/test/converge_test.ts b/packages/build/src/test/converge_test.ts deleted file mode 100644 index c3677fa496f..00000000000 --- a/packages/build/src/test/converge_test.ts +++ /dev/null @@ -1,179 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { converge } from "../internal/board/converge.js"; -import { input } from "../internal/board/input.js"; -import { loopback } from "../internal/board/loopback.js"; -import { defineNodeType } from "../internal/define/define.js"; -import { serialize } from "../internal/board/serialize.js"; -import { board } from "../internal/board/board.js"; -import { array } from "../internal/type-system/array.js"; -import { object } from "../internal/type-system/object.js"; - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -test("converge must have 2 or more arguments", () => { - // @ts-expect-error - converge(); - // @ts-expect-error - converge(input()); - - converge(input(), input()); - converge(input(), input(), input()); - converge(input(), input(), input(), input()); -}); - -test("cannot converge undefined or something weird", () => { - // @ts-expect-error - converge(undefined, undefined); - // @ts-expect-error - converge(converge, converge); -}); - -test("can converge basic types", () => { - // $ExpectType Convergence - converge("foo", "bar"); - // $ExpectType Convergence - converge(123, 456); - // $ExpectType Convergence - converge(null, null); - // $ExpectType Convergence<{ foo: string; } | {}> - converge({}, input({ type: object({ foo: "string" }) })); -}); - -test("nested converge is not allowed", () => { - // @ts-expect-error - converge(converge(input(), input()), input()); -}); - -test("converge creates a union of types", () => { - // $ExpectType Convergence - converge(input(), input({ type: "number" })); - // $ExpectType Convergence - converge(loopback(), loopback({ type: "number" })); - // $ExpectType Convergence - converge( - input(), - loopback({ type: "number" }), - input({ type: array(object({ foo: "number" })) }), - loopback({ type: array(object({ bar: "boolean" })) }) - ); -}); - -test("converge stores the ports in order", () => { - const str = input(); - const num = input({ type: "number" }); - const bool = loopback({ type: "boolean" }); - assert.deepEqual(converge(str, num, bool).ports, [str, num, bool]); - assert.deepEqual(converge(num, bool, str).ports, [num, bool, str]); -}); - -test("converge can be passed as node input", () => { - const def = defineNodeType({ - name: "test", - inputs: { foo: { type: "number" } }, - outputs: {}, - invoke: () => ({}), - }); - def({ - foo: converge(input({ type: "number" }), input({ type: "number" })), - }); -}); - -test("converge of wrong type can't be passed as node input", () => { - const def = defineNodeType({ - name: "test", - inputs: { foo: { type: "number" } }, - outputs: {}, - invoke: () => ({}), - }); - def({ - // @ts-expect-error - foo: converge(123, "bar"), - }); -}); - -test("convergences are serialized as multiple edges", () => { - const def = defineNodeType({ - name: "test", - inputs: { foo: { type: "number" } }, - outputs: { bar: { type: "number" } }, - invoke: ({ foo }) => ({ bar: foo + 1 }), - }); - const a = input({ type: "number" }); - const b = input({ type: "number" }); - const { bar } = def({ - foo: converge(a, 123, b), - }).outputs; - const brd = board({ inputs: { a, b }, outputs: { bar } }); - const bgl = serialize(brd); - assert.deepEqual(bgl, { - edges: [ - { - from: "input-0", - to: "test-0", - out: "a", - in: "foo", - }, - { - from: "input-0", - to: "test-0", - out: "b", - in: "foo", - }, - { - from: "test-0", - to: "output-0", - in: "bar", - out: "bar", - }, - ], - nodes: [ - { - configuration: { - schema: { - properties: { - a: { - type: "number", - }, - b: { - type: "number", - }, - }, - required: ["a", "b"], - type: "object", - }, - }, - id: "input-0", - type: "input", - }, - { - configuration: { - schema: { - properties: { - bar: { - type: "number", - }, - }, - required: ["bar"], - type: "object", - }, - }, - id: "output-0", - type: "output", - }, - { - id: "test-0", - type: "test", - configuration: { - foo: 123, - }, - }, - ], - }); -}); diff --git a/packages/build/src/test/define_test.ts b/packages/build/src/test/define_test.ts deleted file mode 100644 index 230fb702391..00000000000 --- a/packages/build/src/test/define_test.ts +++ /dev/null @@ -1,2121 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/* eslint-disable @typescript-eslint/ban-ts-comment */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { defineNodeType } from "../internal/define/define.js"; -import { object } from "../internal/type-system/object.js"; -import { array } from "../internal/type-system/array.js"; -import { input } from "../internal/board/input.js"; -import type { OutputPort } from "../internal/common/port.js"; -import type { BreadboardError } from "../internal/common/error.js"; - -test("mono/mono", async () => { - const values = { si1: "foo", si2: 123 }; - - // $ExpectType Definition<{ si1: string; si2: number; }, { so1: boolean; so2: null; }, undefined, undefined, never, false, false, false, { si1: { board: false; }; si2: { board: false; }; }> - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - si2: { type: "number" }, - }, - outputs: { - so1: { type: "boolean" }, - so2: { type: "null" }, - }, - invoke: ( - // $ExpectType { si1: string; si2: number; } - staticInputs, - // $ExpectType {} - dynamicInputs - ) => { - assert.deepEqual(staticInputs, values); - assert.deepEqual(dynamicInputs, {}); - return { so1: true, so2: null }; - }, - }); - - // $ExpectType Instance<{ si1: string; si2: number; }, { so1: boolean; so2: null; }, undefined, false, false, false> - const i = d(values); - - assert.ok( - // $ExpectType { si1: InputPort; si2: InputPort; } - i.inputs - ); - assert.ok( - // $ExpectType InputPort - i.inputs.si1 - ); - assert.ok( - // $ExpectType InputPort - i.inputs.si2 - ); - assert.equal( - // @ts-expect-error - i.inputs.di1, - undefined - ); - - assert.ok( - i.outputs satisfies { - so1: OutputPort; - so2: OutputPort; - $error: OutputPort; - } - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.so1 - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.so2 - ); - assert.equal( - // @ts-expect-error - i.outputs.do1, - undefined - ); - - assert.equal( - // $ExpectType undefined - i.primaryInput, - undefined - ); - assert.equal( - // $ExpectType undefined - i.primaryOutput, - undefined - ); - - assert.deepEqual(await d.invoke(values, null as never), { - so1: true, - so2: null, - }); - - const expectedSchema = { - inputSchema: { - type: "object", - properties: { - si1: { - title: "si1", - type: "string", - }, - si2: { - title: "si2", - type: "number", - }, - }, - required: ["si1", "si2"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - so1: { - title: "so1", - type: "boolean", - }, - so2: { - title: "so2", - type: "null", - }, - }, - required: [], - additionalProperties: false, - }, - }; - assert.deepEqual(await d.describe(), expectedSchema); - assert.deepEqual(await d.describe(values), expectedSchema); -}); - -test("poly/mono", async () => { - const values = { si1: "si1", di1: 1, di2: 2 }; - - // $ExpectType Definition<{ si1: string; }, { so1: boolean; }, number, undefined, never, false, false, false, { si1: { board: false; }; }> - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - "*": { type: "number" }, - }, - outputs: { - so1: { type: "boolean" }, - }, - describe: ( - // $ExpectType { si1: string | undefined; } - staticInputs, - // $ExpectType { [x: string]: number; } - dynamicInputs - ) => ({ - inputs: Object.keys(dynamicInputs), - }), - invoke: ( - // $ExpectType { si1: string; } - staticInputs, - // $ExpectType { [x: string]: number; } - dynamicInputs - ) => { - assert.deepEqual(staticInputs, { si1: "si1" }); - assert.deepEqual(dynamicInputs, { di1: 1, di2: 2 }); - return { so1: true }; - }, - }); - - // $ExpectType Instance<{ si1: string; di1: number; di2: number; }, { so1: boolean; }, undefined, false, false, false> - const i = d(values); - - assert.ok( - // $ExpectType { si1: InputPort; di1: InputPort; di2: InputPort; } - i.inputs - ); - assert.ok( - // $ExpectType InputPort - i.inputs.si1 - ); - assert.ok( - // $ExpectType InputPort - i.inputs.di1 - ); - assert.ok( - // $ExpectType InputPort - i.inputs.di2 - ); - assert.equal( - // @ts-expect-error - i.inputs.di3, - undefined - ); - - assert.ok( - i.outputs satisfies { - so1: OutputPort; - $error: OutputPort; - } - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.so1 - ); - assert.equal( - // @ts-expect-error - i.outputs.do1, - undefined - ); - - assert.equal( - // $ExpectType undefined - i.primaryInput, - undefined - ); - assert.equal( - // $ExpectType undefined - i.primaryOutput, - undefined - ); - - assert.deepEqual(await d.invoke(values, null as never), { - so1: true, - }); - - assert.deepEqual(await d.describe(), { - inputSchema: { - type: "object", - properties: { - si1: { - title: "si1", - type: "string", - }, - }, - required: ["si1"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - so1: { - title: "so1", - type: "boolean", - }, - }, - required: [], - additionalProperties: false, - }, - }); - - assert.deepEqual(await d.describe(values), { - inputSchema: { - type: "object", - properties: { - si1: { - title: "si1", - type: "string", - }, - di1: { - title: "di1", - type: "number", - }, - di2: { - title: "di2", - type: "number", - }, - }, - required: ["di1", "di2", "si1"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - so1: { - title: "so1", - type: "boolean", - }, - }, - required: [], - additionalProperties: false, - }, - }); -}); - -test("mono/poly", async () => { - const values = { si1: "si1" }; - - // $ExpectType Definition<{ si1: string; }, { so1: boolean; }, undefined, number, never, false, false, false, { si1: { board: false; }; }> - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { type: "boolean" }, - "*": { type: "number" }, - }, - describe: ( - // $ExpectType { si1: string | undefined; } - staticInputs, - // $ExpectType {} - dynamicInputs - ) => ({ outputs: ["do1"] }), - invoke: ( - // $ExpectType { si1: string; } - staticInputs, - // $ExpectType {} - dynamicInputs - ) => { - assert.deepEqual(staticInputs, values); - assert.deepEqual(dynamicInputs, {}); - return { so1: true, do1: 123 }; - }, - }); - - // $ExpectType Instance<{ si1: string; }, { so1: boolean; }, number, false, false, false> - const i = d(values); - - assert.ok( - // $ExpectType { si1: InputPort; } - i.inputs - ); - assert.ok( - // $ExpectType InputPort - i.inputs.si1 - ); - assert.equal( - // @ts-expect-error - i.inputs.di1, - undefined - ); - - assert.ok( - i.outputs satisfies { - so1: OutputPort; - $error: OutputPort; - } - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.so1 - ); - // @ts-expect-error - i.outputs.do1; - - // $ExpectType undefined - i.primaryInput; - // $ExpectType undefined - i.primaryOutput; - - assert.deepEqual(await d.invoke(values, null as never), { - so1: true, - do1: 123, - }); - - const expectedSchema = { - inputSchema: { - type: "object", - properties: { - si1: { - title: "si1", - type: "string", - }, - }, - required: ["si1"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - so1: { - title: "so1", - type: "boolean", - }, - do1: { - title: "do1", - type: "number", - }, - }, - required: [], - additionalProperties: false, - }, - }; - assert.deepEqual(await d.describe(), expectedSchema); - assert.deepEqual(await d.describe(values), expectedSchema); -}); - -test("poly/poly", async () => { - const values = { si1: "si1", di1: 1, di2: 2 }; - - // $ExpectType Definition<{ si1: string; }, { so1: boolean; }, number, number, never, false, false, false, { si1: { board: false; }; }> - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - "*": { type: "number" }, - }, - outputs: { - so1: { type: "boolean" }, - "*": { type: "number" }, - }, - describe: ( - // $ExpectType { si1: string | undefined; } - staticInputs, - // $ExpectType { [x: string]: number; } - dynamicInputs - ) => ({ outputs: ["do1"] }), - invoke: ( - // $ExpectType { si1: string; } - staticInputs, - // $ExpectType { [x: string]: number; } - dynamicInputs - ) => { - assert.deepEqual(staticInputs, { si1: "si1" }); - assert.deepEqual(dynamicInputs, { di1: 1, di2: 2 }); - return { so1: true, do1: 123 }; - }, - }); - - // $ExpectType Instance<{ si1: string; di1: number; di2: number; }, { so1: boolean; }, number, false, false, false> - const i = d(values); - - assert.ok( - // $ExpectType { si1: InputPort; di1: InputPort; di2: InputPort; } - i.inputs - ); - - assert.ok( - // $ExpectType InputPort - i.inputs.si1 - ); - assert.ok( - // $ExpectType InputPort - i.inputs.di1 - ); - - assert.ok( - // $ExpectType InputPort - i.inputs.di2 - ); - assert.equal( - // @ts-expect-error - i.inputs.di3, - undefined - ); - - assert.ok( - i.outputs satisfies { - so1: OutputPort; - $error: OutputPort; - } - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.so1 - ); - assert.equal( - // @ts-expect-error - i.outputs.do1, - undefined - ); - - assert.ok( - // $ExpectType OutputPort - i.unsafeOutput("do1") - ); - - assert.equal( - // $ExpectType undefined - i.primaryInput, - undefined - ); - assert.equal( - // $ExpectType undefined - i.primaryOutput, - undefined - ); - - assert.deepEqual(await d.invoke(values, null as never), { - so1: true, - do1: 123, - }); - - assert.deepEqual(await d.describe(), { - inputSchema: { - type: "object", - properties: { - si1: { - title: "si1", - type: "string", - }, - }, - required: ["si1"], - additionalProperties: { type: "number" }, - }, - outputSchema: { - type: "object", - properties: { - so1: { - title: "so1", - type: "boolean", - }, - do1: { - title: "do1", - type: "number", - }, - }, - required: [], - additionalProperties: false, - }, - }); - - assert.deepEqual(await d.describe(values), { - inputSchema: { - type: "object", - properties: { - si1: { - title: "si1", - type: "string", - }, - di1: { - title: "di1", - type: "number", - }, - di2: { - title: "di2", - type: "number", - }, - }, - required: ["si1"], - additionalProperties: { type: "number" }, - }, - outputSchema: { - type: "object", - properties: { - so1: { - title: "so1", - type: "boolean", - }, - do1: { - title: "do1", - type: "number", - }, - }, - required: [], - additionalProperties: false, - }, - }); -}); - -test("async invoke function", async () => { - const values = { si1: 123 }; - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "number" }, - }, - outputs: { - so1: { type: "string" }, - }, - invoke: async (staticInputs, dynamicInputs) => { - await new Promise((resolve) => setTimeout(resolve, 1)); - assert.deepEqual(staticInputs, { si1: 123 }); - assert.deepEqual(dynamicInputs, {}); - return { so1: "foo" }; - }, - }); - assert.deepEqual(await d.invoke(values, null as never), { so1: "foo" }); -}); - -test("reflective", async () => { - const values = { si1: "si1", di1: 1, di2: 2 }; - - // $ExpectType Definition<{ si1: string; }, { so1: boolean; }, number, string, never, true, false, false, { si1: { board: false; }; }> - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - "*": { type: "number" }, - }, - outputs: { - so1: { type: "boolean" }, - "*": { type: "string", reflective: true }, - }, - invoke: ( - // $ExpectType { si1: string; } - staticInputs, - // $ExpectType { [x: string]: number; } - dynamicInputs - ) => { - assert.deepEqual(staticInputs, { si1: "si1" }); - assert.deepEqual(dynamicInputs, { di1: 1, di2: 2 }); - return { so1: true }; - }, - }); - - // $ExpectType Instance<{ si1: string; di1: number; di2: number; }, { so1: boolean; di1: string; di2: string; }, undefined, false, false, true> - const i = d(values); - - assert.ok( - // $ExpectType { si1: InputPort; di1: InputPort; di2: InputPort; } - i.inputs - ); - assert.ok( - // $ExpectType InputPort - i.inputs.si1 - ); - assert.ok( - // $ExpectType InputPort - i.inputs.di1 - ); - assert.ok( - // $ExpectType InputPort - i.inputs.di2 - ); - assert.equal( - // @ts-expect-error - i.inputs.di3, - undefined - ); - - assert.ok( - i.outputs satisfies { - so1: OutputPort; - di1: OutputPort; - di2: OutputPort; - $error: OutputPort; - } - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.so1 - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.di1 - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.di2 - ); - assert.equal( - // @ts-expect-error - i.outputs.di3, - undefined - ); - - assert.equal( - // $ExpectType undefined - i.primaryInput, - undefined - ); - assert.equal( - // $ExpectType undefined - i.primaryOutput, - undefined - ); - - assert.deepEqual(await d.invoke(values, null as never), { - so1: true, - }); - - assert.deepEqual(await d.describe(), { - inputSchema: { - type: "object", - properties: { - si1: { type: "string", title: "si1" }, - }, - required: ["si1"], - additionalProperties: { type: "number" }, - }, - outputSchema: { - type: "object", - properties: { - so1: { type: "boolean", title: "so1" }, - }, - required: [], - additionalProperties: false, - }, - }); - - assert.deepEqual(await d.describe(values), { - inputSchema: { - type: "object", - properties: { - di1: { type: "number", title: "di1" }, - di2: { type: "number", title: "di2" }, - si1: { type: "string", title: "si1" }, - }, - required: ["si1"], - additionalProperties: { type: "number" }, - }, - outputSchema: { - type: "object", - properties: { - di1: { type: "number", title: "di1" }, - di2: { type: "number", title: "di2" }, - so1: { type: "boolean", title: "so1" }, - }, - required: [], - additionalProperties: false, - }, - }); -}); - -test("primary input with no other inputs", () => { - const values = { si1: 123 }; - - // $ExpectType Definition<{ si1: number; }, { so1: boolean; }, undefined, undefined, never, false, "si1", false, { si1: { board: false; }; }> - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "number", primary: true }, - }, - outputs: { - so1: { type: "boolean" }, - }, - invoke: ( - // $ExpectType { si1: number; } - staticInputs, - // $ExpectType {} - dynamicInputs - ) => ({ so1: true }), - }); - - // $ExpectType Instance<{ si1: number; }, { so1: boolean; }, undefined, "si1", false, false> - const i = d(values); - - assert.ok( - // $ExpectType { si1: InputPort; } - i.inputs - ); - assert.ok( - // $ExpectType InputPort - i.inputs.si1 - ); - assert.equal( - // @ts-expect-error - i.inputs.di1, - undefined - ); - - assert.ok( - i.outputs satisfies { - so1: OutputPort; - $error: OutputPort; - } - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.so1 - ); - assert.equal( - // @ts-expect-error - i.outputs.di1, - undefined - ); - - assert.ok( - // $ExpectType InputPort - i.primaryInput - ); - assert.equal( - // $ExpectType undefined - i.primaryOutput, - undefined - ); -}); - -test("primary input with another input", () => { - const values = { si1: 123, si2: true }; - - // $ExpectType Definition<{ si1: number; si2: boolean; }, { so1: boolean; }, undefined, undefined, never, false, "si1", false, { si1: { board: false; }; si2: { board: false; }; }> - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "number", primary: true }, - si2: { type: "boolean" }, - }, - outputs: { - so1: { type: "boolean" }, - }, - invoke: ( - // $ExpectType { si1: number; si2: boolean; } - staticInputs, - // $ExpectType {} - dynamicInputs - ) => ({ so1: true }), - }); - - // $ExpectType Instance<{ si1: number; si2: boolean; }, { so1: boolean; }, undefined, "si1", false, false> - const i = d(values); - - assert.ok( - // $ExpectType { si1: InputPort; si2: InputPort; } - i.inputs - ); - assert.ok( - // $ExpectType InputPort - i.inputs.si1 - ); - assert.equal( - // @ts-expect-error - i.inputs.di1, - undefined - ); - - assert.ok( - i.outputs satisfies { - so1: OutputPort; - $error: OutputPort; - } - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.so1 - ); - assert.equal( - // @ts-expect-error - i.outputs.di1, - undefined - ); - - assert.ok( - // $ExpectType InputPort - i.primaryInput - ); - assert.equal( - // $ExpectType undefined - i.primaryOutput, - undefined - ); -}); - -test("primary output with no other outputs", () => { - // $ExpectType Definition<{ si1: number; }, { so1: boolean; }, undefined, undefined, never, false, false, "so1", { si1: { board: false; }; }> - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "number" }, - }, - outputs: { - so1: { type: "boolean", primary: true }, - }, - invoke: ( - // $ExpectType { si1: number; } - staticInputs, - // $ExpectType {} - dynamicInputs - ) => ({ so1: true }), - }); - - // $ExpectType Instance<{ si1: number; }, { so1: boolean; }, undefined, false, "so1", false> - const i = d({ si1: 123 }); - - assert.ok( - // $ExpectType { si1: InputPort; } - i.inputs - ); - assert.ok( - // $ExpectType InputPort - i.inputs.si1 - ); - assert.equal( - // @ts-expect-error - i.inputs.di1, - undefined - ); - - assert.ok( - i.outputs satisfies { - so1: OutputPort; - $error: OutputPort; - } - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.so1 - ); - assert.equal( - // @ts-expect-error - i.outputs.di1, - undefined - ); - - assert.equal( - // $ExpectType undefined - i.primaryInput, - undefined - ); - assert.ok( - // $ExpectType OutputPort - i.primaryOutput - ); -}); - -test("primary output with other outputs", () => { - // $ExpectType Definition<{ si1: number; }, { so1: boolean; so2: number; }, undefined, undefined, never, false, false, "so1", { si1: { board: false; }; }> - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "number" }, - }, - outputs: { - so1: { type: "boolean", primary: true }, - so2: { type: "number" }, - }, - invoke: ( - // $ExpectType { si1: number; } - staticInputs, - // $ExpectType {} - dynamicInputs - ) => ({ so1: true, so2: 123 }), - }); - - // $ExpectType Instance<{ si1: number; }, { so1: boolean; so2: number; }, undefined, false, "so1", false> - const i = d({ si1: 123 }); - - assert.ok( - // $ExpectType { si1: InputPort; } - i.inputs - ); - assert.ok( - // $ExpectType InputPort - i.inputs.si1 - ); - assert.equal( - // @ts-expect-error - i.inputs.di1, - undefined - ); - - assert.ok( - i.outputs satisfies { - so1: OutputPort; - so2: OutputPort; - $error: OutputPort; - } - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.so1 - ); - assert.equal( - // @ts-expect-error - i.outputs.di1, - undefined - ); - - assert.equal( - // $ExpectType undefined - i.primaryInput, - undefined - ); - assert.ok( - // $ExpectType OutputPort - i.primaryOutput - ); -}); - -test("primary input + output", () => { - // $ExpectType Definition<{ si1: number; }, { so1: boolean; }, undefined, undefined, never, false, "si1", "so1", { si1: { board: false; }; }> - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "number", primary: true }, - }, - outputs: { - so1: { type: "boolean", primary: true }, - }, - invoke: ( - // $ExpectType { si1: number; } - staticInputs, - // $ExpectType {} - dynamicInputs - ) => ({ so1: true }), - }); - - // $ExpectType Instance<{ si1: number; }, { so1: boolean; }, undefined, "si1", "so1", false> - const i = d({ si1: 123 }); - - assert.ok( - // $ExpectType { si1: InputPort; } - i.inputs - ); - assert.ok( - // $ExpectType InputPort - i.inputs.si1 - ); - assert.equal( - // @ts-expect-error - i.inputs.di1, - undefined - ); - - assert.ok( - i.outputs satisfies { - so1: OutputPort; - $error: OutputPort; - } - ); - assert.ok( - // $ExpectType OutputPort - i.outputs.so1 - ); - assert.equal( - // @ts-expect-error - i.outputs.di1, - undefined - ); - - assert.ok( - // $ExpectType InputPort - i.primaryInput - ); - assert.ok( - // $ExpectType OutputPort - i.primaryOutput - ); -}); - -test("multiline/javascript", async () => { - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { - type: "string", - format: "multiline", - }, - si2: { - type: "string", - format: "javascript", - }, - }, - outputs: { - so1: { - type: "string", - format: "multiline", - }, - so2: { - type: "string", - format: "javascript", - }, - }, - invoke: () => { - return { so1: "foo", so2: "foo" }; - }, - }); - - assert.deepEqual(await d.describe(), { - inputSchema: { - type: "object", - properties: { - si1: { - title: "si1", - type: "string", - format: "multiline", - }, - si2: { - title: "si2", - type: "string", - format: "javascript", - }, - }, - required: ["si1", "si2"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - so1: { - title: "so1", - type: "string", - format: "multiline", - }, - so2: { - title: "so2", - type: "string", - format: "javascript", - }, - }, - required: [], - additionalProperties: false, - }, - }); -}); - -test("behavior", async () => { - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { - type: "string", - behavior: ["config"], - }, - }, - outputs: { - so1: { - type: "string", - behavior: ["image", "code"], - }, - }, - invoke: () => { - return { so1: "foo" }; - }, - }); - - assert.deepEqual(await d.describe(), { - inputSchema: { - type: "object", - properties: { - si1: { - title: "si1", - type: "string", - behavior: ["config"], - }, - }, - required: ["si1"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - so1: { - title: "so1", - type: "string", - behavior: ["image", "code"], - }, - }, - required: [], - additionalProperties: false, - }, - }); -}); - -test("dynamic port descriptions", async () => { - const d = defineNodeType({ - name: "foo", - inputs: { - "*": { type: "string" }, - }, - outputs: { - "*": { type: "string" }, - }, - describe: (_, inputs) => ({ - inputs: Object.fromEntries( - Object.keys(inputs).map((name) => [ - name, - { description: `input "${name}"` }, - ]) - ), - outputs: Object.fromEntries( - Object.keys(inputs).map((name) => [ - name, - { description: `output "${name}"` }, - ]) - ), - }), - invoke: () => ({}), - }); - - assert.deepEqual(await d.describe({ foo: "foo" }), { - inputSchema: { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - description: 'input "foo"', - }, - }, - required: ["foo"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - description: 'output "foo"', - }, - }, - required: [], - additionalProperties: false, - }, - }); -}); - -test("defaults", async () => { - const d = defineNodeType({ - name: "foo", - inputs: { - a: { - type: "string", - default: "foo", - }, - b: { - type: array("number"), - default: [12, 34], - }, - }, - outputs: { - a: { - type: "string", - }, - b: { - type: array("number"), - }, - }, - invoke: (staticInputs) => staticInputs, - }); - - d({}); - d({ a: "bar" }); - d({ b: [56, 78] }); - d({ a: "bar", b: [56, 78] }); - - assert.deepEqual(await d.invoke({}, null as never), { - a: "foo", - b: [12, 34], - }); - - assert.deepEqual( - await d.invoke( - { - a: "bar", - b: [56, 78], - }, - null as never - ), - { - a: "bar", - b: [56, 78], - } - ); - - const expectedSchema = { - inputSchema: { - type: "object", - properties: { - a: { - title: "a", - type: "string", - default: "foo", - }, - b: { - title: "b", - type: "array", - items: { type: "number" }, - default: [12, 34], - }, - }, - required: [], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - a: { - title: "a", - type: "string", - }, - b: { - title: "b", - type: "array", - items: { type: "number" }, - }, - }, - required: [], - additionalProperties: false, - }, - }; - assert.deepEqual(await d.describe(), expectedSchema); - assert.deepEqual(await d.describe({ si1: "bar", si2: 123 }), expectedSchema); -}); - -test("optional", async () => { - const d = defineNodeType({ - name: "foo", - inputs: { - a: { - type: "string", - }, - b: { - type: array("number"), - optional: true, - }, - }, - outputs: { - serializedStaticInputs: { - type: "string", - }, - }, - invoke: ( - // $ExpectType { a: string; b: number[] | undefined; } - staticInputs - ) => ({ - serializedStaticInputs: JSON.stringify(staticInputs), - }), - }); - - d({ a: "foo" }); - d({ a: "foo", b: [1, 2] }); - - assert.throws(() => - d( - // @ts-expect-error - {} - ) - ); - assert.throws(() => - d( - // @ts-expect-error - { b: [1, 2] } - ) - ); - - assert.deepEqual(await d.invoke({ a: "foo" }, null as never), { - serializedStaticInputs: JSON.stringify({ a: "foo" }), - }); - - assert.deepEqual(await d.invoke({ a: "foo", b: [1, 2] }, null as never), { - serializedStaticInputs: JSON.stringify({ a: "foo", b: [1, 2] }), - }); - - const expectedSchema = { - inputSchema: { - type: "object", - properties: { - a: { - title: "a", - type: "string", - }, - b: { - title: "b", - type: "array", - items: { type: "number" }, - }, - }, - additionalProperties: false, - required: ["a"], - }, - outputSchema: { - type: "object", - properties: { - serializedStaticInputs: { - title: "serializedStaticInputs", - type: "string", - }, - }, - additionalProperties: false, - required: [], - }, - }; - assert.deepEqual(await d.describe(), expectedSchema); - assert.deepEqual(await d.describe({ a: "foo", b: [1, 2] }), expectedSchema); -}); - -test("override title", async () => { - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string", title: "custom1" }, - si2: { type: "number" }, - }, - outputs: { - so1: { type: "boolean" }, - so2: { type: "null", title: "custom2" }, - }, - invoke: () => ({ - so1: true, - so2: null, - }), - }); - assert.deepEqual(await d.describe(), { - inputSchema: { - type: "object", - properties: { - si1: { - title: "custom1", - type: "string", - }, - si2: { - title: "si2", - type: "number", - }, - }, - required: ["si1", "si2"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - so1: { - title: "so1", - type: "boolean", - }, - so2: { - title: "custom2", - type: "null", - }, - }, - required: [], - additionalProperties: false, - }, - }); -}); - -test("error: missing name", () => { - assert.throws( - () => - defineNodeType( - // @ts-expect-error - { - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { type: "boolean" }, - }, - invoke: () => ({ so1: true }), - } - ), - /params.name is required/ - ); -}); - -test("error: missing inputs", () => { - assert.throws( - () => - defineNodeType( - // @ts-expect-error - { - name: "foo", - outputs: { - so1: { type: "boolean" }, - }, - invoke: () => ({ so1: true }), - } - ), - /params.inputs is required/ - ); -}); - -test("error: missing outputs", () => { - assert.throws( - () => - defineNodeType( - // @ts-expect-error - { - name: "foo", - inputs: { - si1: { type: "string" }, - }, - invoke: () => ({}), - } - ), - /params.outputs is required/ - ); -}); - -test("error: missing invoke", () => { - assert.throws( - () => - defineNodeType( - // @ts-expect-error - { - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { type: "boolean" }, - }, - } - ), - /params.invoke is required/ - ); -}); - -test("error: invalid input type", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - si2: { - // @ts-expect-error - type: "foo", - }, - }, - outputs: { - so1: { type: "boolean" }, - }, - invoke: () => ({ so1: true }), - }); -}); - -test("error: invalid output type", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { type: "boolean" }, - so2: { - // @ts-expect-error - type: "foo", - }, - }, - invoke: () => ({ so1: true }), - }); -}); - -test("error: unexpected input property", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { - type: "string", - // @ts-expect-error - bad: true, - }, - }, - outputs: { - so1: { type: "boolean" }, - }, - invoke: () => ({ so1: true }), - }); -}); - -test("error: unexpected output property", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { - type: "boolean", - // @ts-expect-error - bad: true, - }, - }, - invoke: () => ({ so1: true }), - }); -}); - -test("error: invoke missing output", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { - type: "boolean", - }, - so2: { - type: "number", - }, - }, - // @ts-expect-error - invoke: () => ({ - so1: true, - }), - }); -}); - -test("error: invoke returns wrong static type", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { - type: "boolean", - }, - }, - // @ts-expect-error - invoke: () => ({ - so1: 0, - }), - }); -}); - -test("error: static invoke returns excess property", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { type: "boolean" }, - }, - // @ts-expect-error - invoke: () => ({ - so1: true, - do1: "foo", - }), - }); -}); - -test("error: invoke returns wrong dynamic type", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { type: "boolean" }, - "*": { type: "number" }, - }, - // @ts-expect-error - invoke: () => ({ - so1: true, - do1: "foo", - }), - }); -}); - -test("error: primary on dynamic input", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - "*": { - type: "number", - // @ts-expect-error - primary: true, - }, - }, - outputs: { - so1: { type: "boolean" }, - }, - invoke: () => ({ so1: true }), - }); -}); - -test("error: primary on dynamic output", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { type: "boolean" }, - "*": { - type: "number", - // @ts-expect-error - primary: true, - }, - }, - invoke: () => ({ so1: true }), - }); -}); - -test("error: multiple primary inputs", () => { - assert.throws( - () => - defineNodeType({ - name: "foo", - inputs: { - si1: { - type: "string", - // @ts-expect-error - primary: true, - }, - si2: { - type: "string", - // @ts-expect-error - primary: true, - }, - }, - outputs: { - so1: { type: "boolean" }, - }, - invoke: () => ({ so1: true }), - }), - /Too many primaries/ - ); -}); - -test("error: multiple primary outputs", () => { - assert.throws( - () => - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { - type: "boolean", - // @ts-expect-error - primary: true, - }, - so2: { - type: "boolean", - // @ts-expect-error - primary: true, - }, - }, - invoke: () => ({ so1: true, so2: false }), - }), - /Too many primaries/ - ); -}); - -test("error: reflective on input", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { - type: "string", - // @ts-expect-error - reflective: true, - }, - }, - outputs: { - so1: { type: "boolean" }, - }, - invoke: () => ({ so1: true }), - }); -}); - -test("error: reflective on static output", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { - type: "boolean", - // @ts-expect-error - reflective: true, - }, - }, - invoke: () => ({ so1: true }), - }); -}); - -test("error: no instantiate inputs", () => { - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: {}, - invoke: () => ({}), - }); - assert.throws( - () => - // @ts-expect-error - d(), - /args is required/ - ); -}); - -test("error: missing instantiate input", () => { - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: {}, - invoke: () => ({}), - }); - assert.throws( - () => - d( - // @ts-expect-error - {} - ), - /si1 is required/ - ); -}); - -test("error: wrong instantiate static input type", () => { - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: {}, - invoke: () => ({}), - }); - d({ - // @ts-expect-error - si1: 123, - }); -}); - -test("error: wrong instantiate dynamic input type", () => { - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - "*": { type: "string" }, - }, - outputs: {}, - invoke: () => ({}), - }); - d({ - si1: "foo", - // @ts-expect-error - di1: 123, - }); -}); - -test("error: excess instantiate input", () => { - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: {}, - invoke: () => ({}), - }); - assert.throws( - () => - d({ - si1: "foo", - // @ts-expect-error - si2: 123, - }), - /Unexpected input: si2/ - ); -}); - -test("error: mono/poly should not return inputs", () => { - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { type: "string" }, - "*": { type: "string", reflective: true }, - }, - // @ts-expect-error - describe: () => ({ inputs: [], outputs: [] }), - invoke: () => ({ so1: "so1" }), - }); -}); - -test("error: poly/mono should not return outputs", () => { - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - "*": { type: "string" }, - }, - outputs: { - so1: { type: "string" }, - }, - // @ts-expect-error - describe: () => ({ inputs: [], outputs: [] }), - invoke: () => ({ so1: "so1" }), - }); -}); - -test("error: reflective poly/poly should not return outputs", () => { - const d = defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - "*": { type: "string" }, - }, - outputs: { - so1: { type: "string" }, - "*": { type: "string", reflective: true }, - }, - // @ts-expect-error - describe: () => ({ inputs: [], outputs: [] }), - invoke: () => ({ so1: "so1" }), - }); -}); - -test("error: unsafeOutput with entirely static outputs", () => { - const d = defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - so1: { type: "string" }, - }, - invoke: () => ({ so1: "so1" }), - }); - const i = d({}); - assert.throws( - () => - // @ts-expect-error - i.unsafeOutput("do1"), - /unsafeOutput was called unnecessarily on a BreadboardNode. Type "foo" has entirely static outputs. Use ".outputs.do1" instead./ - ); -}); - -test("error: unsafeOutput on reflective node", () => { - const d = defineNodeType({ - name: "foo", - inputs: { - "*": { type: "number" }, - }, - outputs: { - so1: { type: "string" }, - "*": { type: "number", reflective: true }, - }, - invoke: () => ({ so1: "so1" }), - }); - const i = d({}); - assert.throws( - () => - // @ts-expect-error - i.unsafeOutput("do1"), - /unsafeOutput was called unnecessarily on a BreadboardNode. Type "foo" is reflective. Use ".outputs.do1" instead./ - ); -}); - -test("error: unsafeOutput on existing static output", () => { - const d = defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - so1: { type: "string" }, - "*": { type: "number" }, - }, - describe: () => ({ outputs: ["foo"] }), - invoke: () => ({ so1: "so1" }), - }); - const i = d({}); - assert.throws( - () => - i.unsafeOutput( - // @ts-expect-error - "so1" - ), - /unsafeOutput was called unnecessarily on a BreadboardNode. Type "foo" already has a static port called "so1". Use ".outputs.so1" instead./ - ); -}); - -test("error: object types must be plain objects at initialization", () => { - const d = defineNodeType({ - name: "foo", - inputs: { - "*": { type: object({}) }, - }, - outputs: {}, - invoke: () => ({}), - }); - const i = d({ - ok1: {}, - ok2: { foo: 123 }, - - // @ts-expect-error - bad1: 123, - // @ts-expect-error - bad1: "foo", - // @ts-expect-error - bad1: globalThis, - // @ts-expect-error - bad1: Object, - }); -}); - -test("error: default on dynamic input/output or static output", () => { - defineNodeType({ - name: "foo", - inputs: { - "*": { - type: "string", - // @ts-expect-error - default: "foo", - }, - }, - outputs: { - so1: { - type: "string", - // @ts-expect-error - default: "foo", - }, - "*": { - type: "string", - // @ts-expect-error - default: "foo", - }, - }, - describe: () => ({ outputs: [] }), - invoke: () => ({ so1: "foo" }), - }); -}); - -test("error: default does not match type", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { - type: "string", - // @ts-expect-error - default: 123, - }, - }, - outputs: {}, - invoke: () => ({}), - }); -}); - -test("error: can't set optional when there is a default", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { - type: "string", - default: "foo", - // @ts-expect-error - optional: true, - }, - }, - outputs: {}, - invoke: () => ({}), - }); -}); - -test("error: input port can't be called $id", () => { - assert.throws(() => { - const def = defineNodeType({ - name: "foo", - inputs: { - // @ts-expect-error - $id: { type: "string" }, - }, - outputs: {}, - invoke: () => ({}), - }); - def({}); - }, /"\$id" cannot be used as an input port name because it is reserved/); -}); - -test("error: $id must only be a string, not an output port", () => { - const d1 = defineNodeType({ - name: "d1", - inputs: {}, - outputs: { - foo: { type: "string", primary: true }, - }, - invoke: () => ({ foo: "foo" }), - }); - const i1 = d1({}); - - const d2 = defineNodeType({ - name: "d2", - inputs: {}, - outputs: {}, - invoke: () => ({}), - }); - - d2({ $id: "foo" }); - d2({ - // @ts-expect-error - $id: i1.outputs.foo, - }); - d2({ - // @ts-expect-error - $id: input(), - }); -}); - -test("$id should not show up as an instance input", () => { - const d = defineNodeType({ - name: "foo", - inputs: {}, - outputs: {}, - invoke: () => ({}), - }); - const i = d({ $id: "foo" }); - // $ExpectType {} - i.inputs; - // $ExpectType { $error: OutputPort<{ message: string; } | { kind: string; error: { message: string; }; }>; } - i.outputs; - assert.equal( - // @ts-expect-error - i.inputs.$id, - undefined - ); -}); - -test("$id should not show up as a reflective output", () => { - const d = defineNodeType({ - name: "foo", - inputs: { - "*": { - type: "string", - }, - }, - outputs: { - "*": { - type: "string", - reflective: true, - }, - }, - describe: () => ({ inputs: {} }), - invoke: () => ({}), - }); - const i = d({ $id: "foo", notId: "foo" }); - // $ExpectType { notId: InputPort; } - i.inputs; - i.outputs satisfies { - notId: OutputPort; - $error: OutputPort; - }; - assert.equal( - // @ts-expect-error - i.outputs.$id, - undefined - ); - assert.ok(i.outputs.notId); -}); diff --git a/packages/build/src/test/describe_test.ts b/packages/build/src/test/describe_test.ts deleted file mode 100644 index f3aeaee188c..00000000000 --- a/packages/build/src/test/describe_test.ts +++ /dev/null @@ -1,731 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { array, defineNodeType, unsafeSchema } from "@breadboard-ai/build"; -import type { NodeDescriberContext, Schema } from "@google-labs/breadboard"; -import assert from "node:assert/strict"; -import { test } from "node:test"; -import type { NodeDescriberContextWithSchemas } from "../internal/define/describe.js"; - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -test("error: mono/mono should not have describe", () => { - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { type: "string" }, - }, - // @ts-expect-error - describe: () => ({ inputs: [], outputs: [] }), - invoke: () => ({ so1: "so1" }), - }); -}); - -test("error: mono/poly must have describe", () => { - // @ts-expect-error - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - }, - outputs: { - so1: { type: "string" }, - "*": { type: "number" }, - }, - invoke: () => ({ so1: "so1" }), - }); -}); - -test("error: non-reflective poly/poly must have describe", () => { - // @ts-expect-error - defineNodeType({ - name: "foo", - inputs: { - si1: { type: "string" }, - "*": { type: "string" }, - }, - outputs: { - so1: { type: "string" }, - "*": { type: "string" }, - }, - invoke: () => ({ so1: "so1" }), - }); -}); - -test("describe is lenient with odd TypeScript types", () => { - defineNodeType({ - name: "foo", - inputs: { - outputFoo: { type: "boolean" }, - }, - outputs: { - "*": { type: "unknown" }, - }, - describe: ({ outputFoo }) => ({ - /** See {@link DynamicInputPorts} for why this is an interesting case. */ - outputs: outputFoo ? { foo: { description: "foo" } } : {}, - }), - invoke: () => ({}), - }); -}); - -test("static input schema", async () => { - assert.deepEqual( - ( - await defineNodeType({ - name: "foo", - inputs: { foo: { type: "string" } }, - outputs: {}, - invoke: () => ({}), - }).describe() - ).inputSchema, - { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - }, - }, - required: ["foo"], - additionalProperties: false, - } - ); -}); - -test("dynamic input schema with custom describe (closed)", async () => { - assert.deepEqual( - ( - await defineNodeType({ - name: "foo", - inputs: { - foo: { type: "string" }, - "*": { type: "number" }, - }, - outputs: {}, - describe: () => ({ inputs: ["bar"] }), - invoke: () => ({}), - }).describe() - ).inputSchema, - { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - }, - bar: { - title: "bar", - type: "number", - }, - }, - required: ["bar", "foo"], - additionalProperties: false, - } - ); -}); - -test("dynamic input schema with custom describe (open)", async () => { - assert.deepEqual( - ( - await defineNodeType({ - name: "foo", - inputs: { - foo: { type: "string" }, - "*": { type: "number" }, - }, - outputs: {}, - describe: () => ({ inputs: { "*": {} } }), - invoke: () => ({}), - }).describe() - ).inputSchema, - { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - }, - }, - required: ["foo"], - additionalProperties: { type: "number" }, - } - ); -}); - -test("dynamic input schema with default describe passed nothing", async () => { - assert.deepEqual( - ( - await defineNodeType({ - name: "foo", - inputs: { - foo: { type: "string" }, - "*": { type: "number" }, - }, - outputs: {}, - invoke: () => ({}), - }).describe() - ).inputSchema, - { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - }, - }, - required: ["foo"], - additionalProperties: { type: "number" }, - } - ); -}); - -test("dynamic input schema with default describe passed values", async () => { - assert.deepEqual( - ( - await defineNodeType({ - name: "foo", - inputs: { - foo: { type: "string" }, - "*": { type: "number" }, - }, - outputs: {}, - invoke: () => ({}), - }).describe({ a: 1, b: 2 }) - ).inputSchema, - { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - }, - a: { - title: "a", - type: "number", - }, - b: { - title: "b", - type: "number", - }, - }, - required: ["foo"], - additionalProperties: { type: "number" }, - } - ); -}); - -test("dynamic input schema with default describe passed inbound edges", async () => { - assert.deepEqual( - ( - await defineNodeType({ - name: "foo", - inputs: { - foo: { type: "string" }, - "*": { type: "number" }, - }, - outputs: {}, - invoke: () => ({}), - }).describe(undefined, { - type: "object", - properties: { - a: { type: "number" }, - b: { type: "string" }, - }, - }) - ).inputSchema, - { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - }, - a: { - title: "a", - type: "number", - }, - b: { - title: "b", - type: "string", - }, - }, - required: ["foo"], - additionalProperties: { type: "number" }, - } - ); -}); - -test("static output schema", async () => { - assert.deepEqual( - ( - await defineNodeType({ - name: "foo", - inputs: {}, - outputs: { foo: { type: "string" } }, - invoke: () => ({ foo: "foo" }), - }).describe() - ).outputSchema, - { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - }, - }, - // TODO(aomarks) I think this should be required, but currently the visual - // editor will show this in red, which doesn't seem right. - // required: ["foo"], - required: [], - additionalProperties: false, - } - ); -}); - -test("dynamic output schema with custom describe (closed)", async () => { - assert.deepEqual( - ( - await defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - foo: { type: "string" }, - "*": { type: "number" }, - }, - describe: () => ({ outputs: ["bar"] }), - invoke: () => ({ foo: "foo" }), - }).describe() - ).outputSchema, - { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - }, - bar: { - title: "bar", - type: "number", - }, - }, - // TODO(aomarks) I think this should be required, but currently the visual - // editor will show this in red, which doesn't seem right. - // required: ["bar", "foo"], - required: [], - additionalProperties: false, - } - ); -}); - -test("dynamic output schema with custom describe (open)", async () => { - assert.deepEqual( - ( - await defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - foo: { type: "string" }, - "*": { type: "number" }, - }, - describe: () => ({ outputs: { "*": {} } }), - invoke: () => ({ foo: "foo" }), - }).describe() - ).outputSchema, - { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - }, - }, - // TODO(aomarks) I think this should be required, but currently the visual - // editor will show this in red, which doesn't seem right. - // required: ["foo"], - required: [], - additionalProperties: { type: "number" }, - } - ); -}); - -test("async describe", async () => { - assert.deepEqual( - await defineNodeType({ - name: "foo", - inputs: { - "*": { type: "number" }, - }, - outputs: { - "*": { type: "number" }, - }, - describe: async () => { - await new Promise((resolve) => setTimeout(resolve, 1)); - return { - inputs: ["foo"], - outputs: ["bar"], - }; - }, - invoke: () => ({}), - }).describe(), - { - inputSchema: { - type: "object", - properties: { - foo: { - title: "foo", - type: "number", - }, - }, - required: ["foo"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - bar: { - title: "bar", - type: "number", - }, - }, - required: [], - additionalProperties: false, - }, - } - ); -}); - -test("describe receives context", async () => { - const input: NodeDescriberContext = { - base: new URL("http://example.com/"), - outerGraph: { nodes: [], edges: [] }, - wires: { incoming: {}, outgoing: {} }, - }; - const expected: NodeDescriberContextWithSchemas = { - base: new URL("http://example.com/"), - outerGraph: { nodes: [], edges: [] }, - inputSchema: {}, - outputSchema: {}, - wires: { incoming: {}, outgoing: {} }, - }; - let actual: NodeDescriberContext | undefined; - defineNodeType({ - name: "foo", - inputs: { - "*": { type: "number" }, - }, - outputs: { - "*": { type: "number" }, - }, - describe: (_staticInputs, _dynamicInputs, context) => { - actual = context; - return { - inputs: [], - outputs: [], - }; - }, - invoke: () => ({}), - }).describe({}, {}, {}, input); - assert.deepEqual(actual, expected); -}); - -test("describe receives converted inputSchema and outputSchema and can return it", async () => { - let actualContext: NodeDescriberContextWithSchemas | undefined; - const testDefinition = defineNodeType({ - name: "foo", - inputs: { - "*": { type: "number" }, - }, - outputs: { - "*": { type: "number" }, - }, - describe: (_staticInputs, _dynamicInputs, context) => { - actualContext = context; - return { - // Solidfy that the actual input/output ports are valid by returning - // them here so they show up in the description - inputs: { - ...context?.inputSchema, - // Also continue to allow additional ports. - "*": {}, - }, - outputs: { - ...context?.outputSchema, - // Stop allowing additional ports (no "*"). - // But do add some specific other property for some reason. - new: { - type: array("boolean"), - }, - }, - }; - }, - invoke: () => ({}), - }); - - const testContext: NodeDescriberContext = { - base: new URL("http://example.com/"), - outerGraph: { nodes: [], edges: [] }, - wires: { incoming: {}, outgoing: {} }, - }; - - const testInputSchema: Schema = { - type: "object", - properties: { - foo: { - type: "string", - default: "foo", - format: "javascript", - behavior: ["bubble"], - ["weirdThing" as never]: 123, - }, - }, - }; - const testOutputSchema: Schema = { - type: "object", - properties: { - bar: { - type: "number", - ["anotherWeirdThing" as never]: 456, - }, - }, - }; - - const expectedContext: NodeDescriberContextWithSchemas = { - base: new URL("http://example.com/"), - outerGraph: { nodes: [], edges: [] }, - inputSchema: { - foo: { - type: { - jsonSchema: { - behavior: ["bubble"], - default: "foo", - format: "javascript", - type: "string", - weirdThing: 123, - }, - }, - default: "foo", - format: "javascript", - behavior: ["bubble"], - }, - }, - outputSchema: { - bar: { - type: { - jsonSchema: { - anotherWeirdThing: 456, - type: "number", - }, - }, - }, - }, - wires: { incoming: {}, outgoing: {} }, - }; - - const expectedDescription = { - inputSchema: { - type: "object", - properties: { - foo: { - title: "foo", - type: "string", - default: "foo", - behavior: ["bubble"], - format: "javascript", - weirdThing: 123, - }, - }, - required: [], - additionalProperties: { - type: "number", - }, - }, - outputSchema: { - type: "object", - properties: { - bar: { - title: "bar", - type: "number", - anotherWeirdThing: 456, - }, - new: { - title: "new", - type: "array", - items: { - type: "boolean", - }, - }, - }, - required: [], - additionalProperties: false, - }, - }; - - const actualDescription = await testDefinition.describe( - {}, - testInputSchema, - testOutputSchema, - testContext - ); - assert.deepEqual(actualContext, expectedContext); - assert.deepEqual(actualDescription, expectedDescription); -}); - -test("describe receives defaults with undefined values", async () => { - let describeRan = false; - defineNodeType({ - name: "foo", - inputs: { - withDefault: { type: "string", default: "DEFAULT1" }, - withoutDefault: { type: "string" }, - "*": { type: "string" }, - }, - outputs: {}, - describe: ({ withDefault, withoutDefault }) => { - assert.equal( - // $ExpectType string - withDefault, - "DEFAULT1" - ); - assert.equal( - // $ExpectType string | undefined - withoutDefault, - undefined - ); - describeRan = true; - return { - inputs: [], - }; - }, - invoke: () => ({}), - }).describe(undefined, {}, null as never); - assert.equal(describeRan, true); -}); - -test("describe receives defaults with overrides", async () => { - let describeRan = false; - defineNodeType({ - name: "foo", - inputs: { - withDefault: { type: "string", default: "DEFAULT1" }, - withDefaultOverride: { type: "string", default: "DEFAULT2" }, - withoutDefault: { type: "string" }, - withoutDefaultOverride: { type: "string" }, - "*": { type: "string" }, - }, - outputs: {}, - describe: ({ - withDefault, - withDefaultOverride, - withoutDefault, - withoutDefaultOverride, - }) => { - assert.equal( - // $ExpectType string - withDefault, - "DEFAULT1" - ); - assert.equal( - // $ExpectType string - withDefaultOverride, - "OVERRIDE1" - ); - assert.equal( - // $ExpectType string | undefined - withoutDefault, - undefined - ); - assert.equal( - // $ExpectType string | undefined - withoutDefaultOverride, - "OVERRIDE2" - ); - describeRan = true; - return { - inputs: [], - }; - }, - invoke: () => ({}), - }).describe( - { - withDefaultOverride: "OVERRIDE1", - withoutDefaultOverride: "OVERRIDE2", - }, - {}, - {}, - null as never - ); - assert.equal(describeRan, true); -}); - -test("unsafeSchema can be used to force a raw JSON schema", async () => { - assert.deepEqual( - await defineNodeType({ - name: "foo", - inputs: { - si1: { type: array("number") }, - "*": { type: "number" }, - }, - outputs: { - so1: { type: array("string") }, - "*": { type: "number" }, - }, - describe: () => ({ - inputs: unsafeSchema({ - properties: { - foo: { type: "number" }, - bar: { type: "string" }, - }, - required: ["bar"], - additionalProperties: true, - }), - outputs: unsafeSchema({ - properties: { - bar: { type: "string" }, - }, - }), - }), - invoke: () => ({ so1: ["foo"] }), - }).describe(), - { - inputSchema: { - type: "object", - properties: { - si1: { - title: "si1", - type: "array", - items: { type: "number" }, - }, - foo: { - type: "number", - }, - bar: { - type: "string", - }, - }, - required: ["si1", "bar"], - additionalProperties: true, - }, - outputSchema: { - type: "object", - properties: { - so1: { - title: "so1", - type: "array", - items: { type: "string" }, - }, - bar: { - type: "string", - }, - }, - required: [], - }, - } - ); -}); diff --git a/packages/build/src/test/enumeration_test.ts b/packages/build/src/test/enumeration_test.ts deleted file mode 100644 index abc6d044949..00000000000 --- a/packages/build/src/test/enumeration_test.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { enumeration, array } from "@breadboard-ai/build"; -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { toJSONSchema } from "../internal/type-system/type.js"; - -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -test("1 string", () => { - assert.deepEqual( - toJSONSchema( - // $ExpectType AdvancedBreadboardType<"foo"> - enumeration("foo") - ), - { type: "string", enum: ["foo"] } - ); -}); - -test("3 strings", () => { - assert.deepEqual( - toJSONSchema( - // $ExpectType AdvancedBreadboardType<"foo" | "bar" | "baz"> - enumeration("foo", "bar", "baz") - ), - { type: "string", enum: ["foo", "bar", "baz"] } - ); -}); - -test("2 numbers", () => { - assert.deepEqual( - toJSONSchema( - // $ExpectType AdvancedBreadboardType<123 | 456> - enumeration(123, 456) - ), - { type: "number", enum: [123, 456] } - ); -}); - -test("boolean", () => { - assert.deepEqual( - toJSONSchema( - // $ExpectType AdvancedBreadboardType - enumeration(true) - ), - { type: "boolean", enum: [true] } - ); -}); - -test("null", () => { - assert.deepEqual( - toJSONSchema( - // $ExpectType AdvancedBreadboardType - enumeration(null) - ), - { type: "null", enum: [null] } - ); -}); - -test("multiple types", () => { - assert.deepEqual( - toJSONSchema( - // $ExpectType AdvancedBreadboardType - enumeration("foo", true) - ), - { enum: ["foo", true] } - ); -}); - -test("error: no values", () => { - // @ts-expect-error - assert.throws(() => enumeration(), /enumeration needs at least one value/); -}); - -test("error: undefined", () => { - assert.throws( - () => - // @ts-expect-error - enumeration(undefined), - /enumeration values must be string, number, boolean, or null. Got undefined./ - ); -}); - -test("error: object", () => { - assert.throws( - () => - // @ts-expect-error - enumeration({}), - /enumeration values must be string, number, boolean, or null. Got object./ - ); -}); - -test("error: unknown", () => { - // @ts-expect-error - enumeration(null as unknown); -}); - -test("error: other advanced type", () => { - assert.throws( - () => - // @ts-expect-error - enumeration(array("string")), - /enumeration values must be string, number, boolean, or null. Got object./ - ); -}); diff --git a/packages/build/src/test/error_test.ts b/packages/build/src/test/error_test.ts deleted file mode 100644 index ab19eb8c100..00000000000 --- a/packages/build/src/test/error_test.ts +++ /dev/null @@ -1,135 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -import { defineNodeType } from "@breadboard-ai/build"; -import assert from "node:assert/strict"; -import { test } from "node:test"; - -test("returns $error as ErrorCapability given {message}", async () => { - const def = defineNodeType({ - name: "test", - inputs: {}, - outputs: {}, - invoke: () => ({ $error: { message: "oh no" } }), - }); - assert.deepEqual(await def.invoke({}, null as never), { - $error: { kind: "error", error: { message: "oh no" } }, - }); -}); - -test("can return $error as ErrorCapability given string", async () => { - const def = defineNodeType({ - name: "test", - inputs: {}, - outputs: {}, - invoke: () => ({ $error: "oh no" }), - }); - assert.deepEqual(await def.invoke({}, null as never), { - $error: { kind: "error", error: { message: "oh no" } }, - }); -}); - -test("can return $error as ErrorCapability given ErrorCapability", async () => { - const def = defineNodeType({ - name: "test", - inputs: {}, - outputs: {}, - invoke: () => ({ $error: { kind: "error", error: { message: "oh no" } } }), - }); - assert.deepEqual(await def.invoke({}, null as never), { - $error: { kind: "error", error: { message: "oh no" } }, - }); -}); - -test("throwing returns an $error with Internal Exception prefix and stack trace", async () => { - const def = defineNodeType({ - name: "test", - inputs: {}, - outputs: {}, - invoke: () => { - throw new Error("internal details"); - }, - }); - const result = await def.invoke({}, null as never); - const message = (result?.$error as { message?: string } | undefined)?.message; - assert.match( - message!, - /Internal Exception: internal details\n.*error_test.ts.*/ - ); -}); - -test("must include message in $error object", () => { - defineNodeType({ - name: "test", - inputs: {}, - outputs: {}, - // @ts-expect-error - invoke: () => ({ $error: { notmessage: "oh no" } }), - }); -}); - -test("can't return other properties when returning $error", () => { - defineNodeType({ - name: "test", - inputs: {}, - outputs: { - foo: { type: "number" }, - }, - // @ts-expect-error - invoke: () => ({ - $error: "oh no", - foo: 123, - }), - }); -}); - -test("nodes that return $error have an $error output", () => { - const def = defineNodeType({ - name: "test", - inputs: {}, - outputs: {}, - invoke: () => ({ $error: "oh no" }), - }); - const inst = def({}); - assert.ok( - // $ExpectType OutputPort<{ message: string; } | { kind: string; error: { message: string; }; }> - inst.outputs.$error - ); -}); - -test("all nodes have an $error output even if they don't return $error", () => { - const def = defineNodeType({ - name: "test", - inputs: {}, - outputs: {}, - invoke: () => ({}), - }); - const inst = def({}); - assert.ok( - // $ExpectType OutputPort<{ message: string; } | { kind: string; error: { message: string; }; }> - inst.outputs.$error - ); -}); - -test("can't declare node with $error output because it's automatic", () => { - assert.throws( - () => - defineNodeType({ - name: "test", - inputs: {}, - outputs: { - // @ts-expect-error - $error: { - type: "string", - }, - }, - invoke: () => ({}), - }), - /"\$error" cannot be used as an output port name because it is reserved/ - ); -}); diff --git a/packages/build/src/test/input_test.ts b/packages/build/src/test/input_test.ts deleted file mode 100644 index db8c25be6b3..00000000000 --- a/packages/build/src/test/input_test.ts +++ /dev/null @@ -1,584 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { - anyOf, - array, - board, - defineNodeType, - object, - output, - serialize, -} from "../index.js"; -import { inputNode } from "../internal/board/board.js"; -import { - input, - rawInput, - type GenericSpecialInput, -} from "../internal/board/input.js"; -import { jsonSchema } from "../internal/type-system/json-schema.js"; -import type { - BreadboardType, - JsonSerializable, -} from "../internal/type-system/type.js"; - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -function checkInput( - input: T, - expectedType: BreadboardType, - expectedExamples?: JsonSerializable[] -): T { - assert.equal(input.type, expectedType); - assert.deepEqual(input.examples, expectedExamples); - return input; -} - -test("defaults to string", () => { - // $ExpectType Input - checkInput(input(), "string"); - - // $ExpectType Input - checkInput(input({ optional: true }), "string"); - - checkInput( - // $ExpectType Input - input({ description: "Description" }), - "string" - ); - - checkInput( - // $ExpectType Input - input({ title: "Title" }), - "string" - ); - - checkInput( - // $ExpectType Input - input({ description: "Description", title: "Title" }), - "string" - ); -}); - -test("only type", () => { - // $ExpectType Input - checkInput(input({ type: "string" }), "string"); - - // $ExpectType Input - checkInput(input({ type: "string", optional: true }), "string"); - - // $ExpectType Input - checkInput(input({ type: "number" }), "number"); - - // $ExpectType Input - checkInput(input({ type: "boolean" }), "boolean"); - - // $ExpectType Input - input({ type: anyOf("string", "number") }); - - // $ExpectType Input<{ foo: string; }> - input({ type: object({ foo: "string" }) }); -}); - -test("only default", () => { - // $ExpectType InputWithDefault - checkInput(input({ default: "foo" }), "string"); - - // $ExpectType InputWithDefault - checkInput(input({ default: 42 }), "number"); - - // $ExpectType InputWithDefault - checkInput(input({ default: true }), "boolean"); -}); - -test("type and default", () => { - // $ExpectType InputWithDefault - checkInput(input({ type: "string", default: "foo" }), "string"); - - // $ExpectType InputWithDefault - checkInput(input({ type: "number", default: 42 }), "number"); - - // $ExpectType InputWithDefault - checkInput(input({ type: "boolean", default: true }), "boolean"); - - // $ExpectType InputWithDefault<{ foo: string[]; }> - input({ - type: object({ foo: array("string") }), - default: { foo: ["bar"] }, - }); -}); - -test("type and default and examples", () => { - // $ExpectType InputWithDefault - checkInput( - input({ type: "string", default: "foo", examples: ["a", "b"] }), - "string", - ["a", "b"] - ); - - // $ExpectType InputWithDefault - checkInput( - input({ type: "number", default: 42, examples: [1, 2, 3] }), - "number", - [1, 2, 3] - ); - - // $ExpectType InputWithDefault - checkInput( - input({ type: "boolean", default: true, examples: [true, false] }), - "boolean", - [true, false] - ); - - // $ExpectType InputWithDefault<{ foo: string[]; }> - input({ - type: object({ foo: array("string") }), - default: { foo: ["bar"] }, - examples: [{ foo: ["a"] }, { foo: ["b"] }], - }); -}); - -test("just examples", () => { - // $ExpectType Input - checkInput(input({ examples: [1, 2] }), "number", [1, 2]); - - // $ExpectType Input - checkInput(input({ examples: [1, 2], optional: true }), "number", [1, 2]); -}); - -test("default doesn't match type", () => { - input({ - // TODO(aomarks) Only default should error ideally. - // @ts-expect-error - type: "string", - // @ts-expect-error - default: 42, - }); - - input({ - // TODO(aomarks) Only default should error ideally. - // @ts-expect-error - type: "number", - // @ts-expect-error - default: true, - }); - - input({ - // TODO(aomarks) Only default should error ideally. - // @ts-expect-error - type: "boolean", - // @ts-expect-error - default: "foo", - }); - - input({ - type: object({ foo: array("string") }), - default: { - foo: [ - // @ts-expect-error - 42, - ], - }, - }); -}); - -test("examples don't match type", () => { - input({ - type: "string", - examples: [ - // @ts-expect-error - 42, - ], - }); - - input({ - type: "number", - examples: [ - // @ts-expect-error - true, - ], - }); - - input({ - type: "boolean", - examples: [ - // @ts-expect-error - "foo", - ], - }); - - input({ - type: object({ foo: array("string") }), - // @ts-expect-error - examples: [{ foo: [42] }], - }); -}); - -test("invalid types", () => { - // @ts-expect-error - input({ type: null }); - - // @ts-expect-error - input({ type: "foo" }); -}); - -test("invalid defaults", () => { - // @ts-expect-error - assert.throws(() => input({ default: null }), /Unknown default type: null/); - - assert.throws( - // @ts-expect-error - () => input({ default: { foo: "bar" } }), - /Error: Unknown default type: {"foo":"bar"}/ - ); -}); - -test("invalid examples", () => { - // @ts-expect-error - input({ examples: null }); - - // @ts-expect-error - input({ examples: { foo: "bar" } }); -}); - -test("multiple input nodes with ids and metadata", () => { - const a = input(); - const b = input({ type: "number" }); - const c = input({ type: "boolean" }); - - const { d } = defineNodeType({ - name: "test", - inputs: { - a: { type: "string" }, - b: { type: "number" }, - c: { type: "boolean" }, - }, - outputs: { - d: { type: "string" }, - }, - invoke: () => ({ d: "foo" }), - })({ a, b, c }).outputs; - - // $ExpectType BoardDefinition<{ a: string; b: number; c: boolean; } | { b: number; c: boolean; } | { c: boolean; a: string; }, { d: string; }> - const brd = board({ - inputs: [ - inputNode({ a, b, c }), - inputNode( - { - b, - c, - }, - { - id: "foo", - title: "Foo Title", - description: "Foo Desc", - } - ), - inputNode({ c, a }), - ], - outputs: { - d, - }, - }); - assert.deepEqual(serialize(brd), { - edges: [ - { from: "foo", to: "test-0", out: "b", in: "b" }, - { from: "input-1", to: "test-0", out: "a", in: "a" }, - { from: "input-1", to: "test-0", out: "c", in: "c" }, - { from: "test-0", to: "output-0", out: "d", in: "d" }, - ], - nodes: [ - { - id: "foo", - type: "input", - configuration: { - schema: { - type: "object", - properties: { b: { type: "number" }, c: { type: "boolean" } }, - required: ["b", "c"], - }, - }, - metadata: { title: "Foo Title", description: "Foo Desc" }, - }, - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - a: { type: "string" }, - b: { type: "number" }, - c: { type: "boolean" }, - }, - required: ["a", "b", "c"], - }, - }, - }, - { - id: "input-1", - type: "input", - configuration: { - schema: { - type: "object", - properties: { a: { type: "string" }, c: { type: "boolean" } }, - required: ["a", "c"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { d: { type: "string" } }, - required: ["d"], - }, - }, - }, - { id: "test-0", type: "test", configuration: {} }, - ], - }); -}); - -test("can't be optional with default", () => { - input({ optional: true, type: "string" }); - // @ts-expect-error - input({ optional: true, type: "string", default: "foo" }); - // @ts-expect-error - input({ optional: true, default: "foo" }); -}); - -test("optional inputs aren't required in JSON schema", () => { - const req = input({ type: "number" }); - const opt = input({ type: "number", optional: true }); - - // $ExpectType Definition<{ foo: number; bar: number; }, { baz: number; }, undefined, undefined, "bar", false, false, false, { foo: { board: false; }; bar: { board: false; }; }> - const def = defineNodeType({ - name: "test", - inputs: { - foo: { type: "number" }, - bar: { type: "number", optional: true }, - }, - outputs: { - baz: { type: "number" }, - }, - invoke: () => ({ baz: 123 }), - }); - - const { baz } = def({ foo: req, bar: opt }).outputs; - - // $ExpectType BoardDefinition<{ opt?: number | undefined; req: number; }, { baz: number; }> - const brd = board({ - inputs: { - req, - opt, - }, - outputs: { - baz, - }, - }); - assert.deepEqual(serialize(brd), { - edges: [ - { from: "input-0", to: "test-0", out: "opt", in: "bar" }, - { from: "input-0", to: "test-0", out: "req", in: "foo" }, - { from: "test-0", to: "output-0", out: "baz", in: "baz" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - opt: { type: "number" }, - req: { type: "number" }, - }, - required: ["req"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { baz: { type: "number" } }, - required: ["baz"], - }, - }, - }, - { id: "test-0", type: "test", configuration: {} }, - ], - }); -}); - -test("input directly to output", () => { - const foo = input(); - const bar = input({ type: "number", default: 42 }); - const brd = board({ - inputs: { fooIn: foo, barIn: bar }, - outputs: { fooOut: foo, barOut: bar }, - }); - assert.deepEqual(serialize(brd), { - edges: [ - { from: "input-0", to: "output-0", out: "barIn", in: "barOut" }, - { from: "input-0", to: "output-0", out: "fooIn", in: "fooOut" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - barIn: { type: "number", default: "42" }, - fooIn: { type: "string" }, - }, - required: ["fooIn"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - barOut: { type: "number" }, - fooOut: { type: "string" }, - }, - required: ["barOut", "fooOut"], - }, - }, - }, - ], - }); -}); - -test("input directly to output with description", () => { - const foo = input({ description: "Foo IN" }); - const bar = input({ type: "number", description: "Bar IN", default: 42 }); - const brd = board({ - inputs: { fooIn: foo, barIn: bar }, - outputs: { - fooOut: output(foo, { description: "Foo OUT" }), - barOut: output(bar, { description: "Bar OUT" }), - }, - }); - assert.deepEqual(serialize(brd), { - edges: [ - { from: "input-0", to: "output-0", out: "barIn", in: "barOut" }, - { from: "input-0", to: "output-0", out: "fooIn", in: "fooOut" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - barIn: { type: "number", description: "Bar IN", default: "42" }, - fooIn: { type: "string", description: "Foo IN" }, - }, - required: ["fooIn"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - barOut: { type: "number", description: "Bar OUT" }, - fooOut: { type: "string", description: "Foo OUT" }, - }, - required: ["barOut", "fooOut"], - }, - }, - }, - ], - }); -}); - -test("can create and serialize a raw input", () => { - const schema = input({ type: jsonSchema }); - // $ExpectType Instance<{ schema: Schema; }, {}, JsonSerializable, false, false, false> - const raw = rawInput({ $metadata: { title: "A regular old input" }, schema }); - const bgl = serialize( - board({ - inputs: { schema }, - outputs: { - foo: raw.unsafeOutput("foo"), - }, - }) - ); - assert.deepEqual(bgl, { - edges: [ - { from: "input-0", to: "input-1", out: "schema", in: "schema" }, - { from: "input-1", to: "output-0", out: "foo", in: "foo" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - schema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - behavior: ["json-schema"], - }, - }, - required: ["schema"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - foo: { - type: [ - "array", - "boolean", - "null", - "number", - "object", - "string", - ], - }, - }, - required: ["foo"], - }, - }, - }, - { - id: "input-1", - type: "input", - configuration: {}, - metadata: { title: "A regular old input" }, - }, - ], - }); -}); diff --git a/packages/build/src/test/invoke_test.ts b/packages/build/src/test/invoke_test.ts deleted file mode 100644 index 4c77a03a1cb..00000000000 --- a/packages/build/src/test/invoke_test.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { NodeHandlerContext } from "@google-labs/breadboard"; -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { defineNodeType } from "../internal/define/define.js"; - -test("invoke receives context", async () => { - const expected: NodeHandlerContext = { - base: new URL("http://example.com/"), - outerGraph: { nodes: [], edges: [] }, - }; - let actual: NodeHandlerContext | undefined; - defineNodeType({ - name: "foo", - inputs: {}, - outputs: {}, - invoke: (_staticInputs, _dynamicInputs, context) => { - actual = context; - return {}; - }, - }).invoke({}, expected); - assert.deepEqual(actual, expected); -}); diff --git a/packages/build/src/test/kit_test.ts b/packages/build/src/test/kit_test.ts deleted file mode 100644 index ee6d8bc2c32..00000000000 --- a/packages/build/src/test/kit_test.ts +++ /dev/null @@ -1,302 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { board } from "../internal/board/board.js"; -import { input } from "../internal/board/input.js"; -import { defineNodeType } from "../internal/define/define.js"; -import { kit } from "../internal/kit.js"; -import { - board as oldBoard, - type GraphDescriptor, - type Kit, - type KitConstructor, - type NodeFactory, - type NodeHandlerObject, -} from "@google-labs/breadboard"; -import { serialize } from "../internal/board/serialize.js"; - -const testDiscrete = defineNodeType({ - name: "discreteComponent", - metadata: { - description: "Discrete Description", - }, - inputs: { - str: { - type: "string", - }, - }, - outputs: { - str: { - type: "string", - }, - }, - invoke: ({ str }) => ({ str }), -}); - -const numInput = input({ type: "number" }); -const testBoard = board({ - id: "boardComponent", - description: "Board Description", - inputs: { num: numInput }, - outputs: { num: numInput }, -}); - -const testDescriptor: GraphDescriptor = { - title: "BGL Title", - description: "BGL Description", - metadata: { - icon: "robot", - }, - nodes: [], - edges: [], -}; - -const testKit = await kit({ - title: "test_title", - url: "test_url", - version: "test_version", - description: "test_description", - components: { - foo: testDiscrete, - bar: testBoard, - baz: testDescriptor, - }, -}); - -test("is a kit", () => { - testKit satisfies Kit & { - handlers: { foo: NodeHandlerObject; bar: NodeHandlerObject }; - }; - assert.deepEqual(Object.keys(testKit.handlers), ["foo", "bar", "baz"]); - const { foo, bar, baz } = testKit.handlers; - assert.equal(typeof foo.invoke, "function"); - assert.equal(typeof bar.invoke, "function"); - assert.equal(typeof baz.invoke, "function"); - assert.equal(typeof foo.describe, "function"); - assert.equal(typeof bar.describe, "function"); - assert.equal(typeof baz.describe, "function"); -}); - -test("is a kit factory for itself", () => { - testKit satisfies KitConstructor< - Kit & { - handlers: { foo: NodeHandlerObject; bar: NodeHandlerObject }; - } - >; - const instantiatedTestKit = new testKit(undefined as unknown as NodeFactory); - assert.deepEqual(Object.keys(instantiatedTestKit.handlers), [ - "foo", - "bar", - "baz", - ]); - const { foo, bar, baz } = instantiatedTestKit.handlers; - assert.equal(typeof foo.invoke, "function"); - assert.equal(typeof bar.invoke, "function"); - assert.equal(typeof baz.invoke, "function"); - assert.equal(typeof foo.describe, "function"); - assert.equal(typeof bar.describe, "function"); - assert.equal(typeof baz.describe, "function"); -}); - -test("kit handles discrete component", () => { - assert.ok( - // $ExpectType Definition<{ str: string; }, { str: string; }, undefined, undefined, never, false, false, false, { str: { board: false; }; }> - testKit.foo - ); - assert.equal(testKit.foo.metadata.description, "Discrete Description"); -}); - -test("kit handles board component", () => { - assert.ok( - // $ExpectType BoardDefinition<{ num: number; }, { num: number; }> - testKit.bar - ); - assert.equal(testKit.bar.description, "Board Description"); -}); - -test("kit handles BGL component", () => { - assert.ok( - // $ExpectType GraphDescriptor - testKit.baz - ); - assert.equal(testKit.baz.title, "BGL Title"); - assert.equal(testKit.baz.description, "BGL Description"); - assert.equal(testKit.baz.metadata?.icon, "robot"); -}); - -test("can invoke discrete component with old API", async () => { - const legacyTestKit = await testKit.legacy(); - const oldBoardInstance = await oldBoard(() => { - const node = legacyTestKit.foo({ str: "foo" }); - return { - str: node.str, - }; - }); - const bgl = await oldBoardInstance.serialize(); - assert.deepEqual(bgl, { - nodes: [ - { - id: "output-2", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - str: { - title: "str", - type: "string", - }, - }, - }, - }, - }, - { - id: "foo-3", - type: "foo", - configuration: { - str: "foo", - }, - }, - ], - edges: [ - { - from: "foo-3", - out: "str", - to: "output-2", - in: "str", - }, - ], - graphs: {}, - }); -}); - -test("can invoke board component with old API", async () => { - const legacyTestKit = await testKit.legacy(); - const oldBoardInstance = await oldBoard(() => { - const num = legacyTestKit.bar({ num: 32 }); - return { - num, - }; - }); - const bgl = await oldBoardInstance.serialize(); - assert.deepEqual(bgl, { - nodes: [ - { - id: "output-2", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - num: { - title: "num", - type: "number", - }, - }, - }, - }, - }, - { - id: "bar-3", - type: "bar", - configuration: { - num: 32, - }, - }, - ], - edges: [ - { - from: "bar-3", - out: "num", - to: "output-2", - in: "num", - }, - ], - graphs: {}, - }); -}); - -test("can invoke discrete component with new API", () => { - const str = testKit.foo({ str: "foo" }).outputs.str; - const newBoardInstance = board({ inputs: {}, outputs: { str } }); - const bgl = serialize(newBoardInstance); - assert.deepEqual(bgl, { - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - str: { - type: "string", - }, - }, - required: ["str"], - }, - }, - }, - { - id: "foo-0", - type: "foo", - configuration: { - str: "foo", - }, - }, - ], - edges: [ - { - from: "foo-0", - out: "str", - to: "output-0", - in: "str", - }, - ], - }); -}); - -test("can invoke board component with new API", () => { - const num = testKit.bar({ num: 32 }).outputs.num; - const newBoardInstance = board({ inputs: {}, outputs: { num } }); - const bgl = serialize(newBoardInstance); - assert.deepEqual(bgl, { - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - num: { - type: "number", - }, - }, - required: ["num"], - }, - }, - }, - { - id: "bar-0", - type: "bar", - configuration: { - num: 32, - }, - }, - ], - edges: [ - { - from: "bar-0", - out: "num", - to: "output-0", - in: "num", - }, - ], - }); -}); diff --git a/packages/build/src/test/loopback_test.ts b/packages/build/src/test/loopback_test.ts deleted file mode 100644 index 440ca2a48c8..00000000000 --- a/packages/build/src/test/loopback_test.ts +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { anyOf, defineNodeType, input, object } from "../index.js"; -import { loopback } from "../internal/board/loopback.js"; -import type { BreadboardType } from "../internal/type-system/type.js"; - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -function assertType( - loopback: T, - expected: BreadboardType -): T { - assert.equal(loopback.type, expected); - return loopback; -} - -test("defaults to string", () => { - // $ExpectType Loopback - assertType(loopback(), "string"); -}); - -test("only type", () => { - // $ExpectType Loopback - assertType(loopback({ type: "string" }), "string"); - - // $ExpectType Loopback - assertType(loopback({ type: "number" }), "number"); - - // $ExpectType Loopback - assertType(loopback({ type: "boolean" }), "boolean"); - - // $ExpectType Loopback - loopback({ type: anyOf("string", "number") }); - - // $ExpectType Loopback<{ foo: string; }> - loopback({ type: object({ foo: "string" }) }); -}); - -test("invalid types", () => { - // @ts-expect-error - loopback({ type: undefined }); - - // @ts-expect-error - loopback({ type: null }); - - // @ts-expect-error - loopback({ type: "foo" }); -}); - -test("error: missing resolve value", () => { - // @ts-expect-error - loopback().resolve(); - - // @ts-expect-error - loopback().resolve(undefined); - - // @ts-expect-error - loopback().resolve(null); -}); - -test("error: resolve with raw value", () => { - // @ts-expect-error - loopback().resolve("foo"); -}); - -test("error: resolve with input", () => { - // @ts-expect-error - loopback().resolve(input()); -}); - -test("error: resolve with another loopback", () => { - // @ts-expect-error - loopback().resolve(loopback()); -}); - -test("error: resolve with wrong type", () => { - const node = defineNodeType({ - name: "node", - inputs: {}, - outputs: { a: { type: "string" } }, - invoke: () => ({ a: "a" }), - })({}); - const p = loopback({ type: "number" }); - // @ts-expect-error - p.resolve(node.outputs.a); -}); - -test("error: resolve multiple times", () => { - const node = defineNodeType({ - name: "node", - inputs: {}, - outputs: { a: { type: "string" } }, - invoke: () => ({ a: "a" }), - })({}); - const p = loopback(); - p.resolve(node.outputs.a); - assert.throws( - () => p.resolve(node.outputs.a), - /Loopback has already been resolved/ - ); -}); diff --git a/packages/build/src/test/nested-boards_test.ts b/packages/build/src/test/nested-boards_test.ts deleted file mode 100644 index afcc92cd686..00000000000 --- a/packages/build/src/test/nested-boards_test.ts +++ /dev/null @@ -1,244 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -import { - anyOf, - board, - defineNodeType, - input, - object, - serialize, -} from "@breadboard-ai/build"; -import assert from "node:assert/strict"; -import { test } from "node:test"; - -// $ExpectType Definition<{ board: string | { [x: string]: JsonSerializable; }; }, { result: JsonSerializable; }, undefined, undefined, never, false, false, false, { board: { board: true; }; }> -const nodeThatTakesBoard = defineNodeType({ - name: "boardnode", - inputs: { - board: { - type: anyOf("string", object({}, "unknown")), - behavior: ["board"], - }, - }, - outputs: { - result: { - type: "unknown", - }, - }, - invoke: () => ({ result: 123 }), -}); - -const nestedBoard = (() => { - const strToNumNode = defineNodeType({ - name: "str2num", - inputs: { - str: { - type: "string", - }, - }, - outputs: { - num: { - type: "number", - }, - }, - invoke: ({ str }) => ({ num: Number(str) }), - }); - const str = input(); - const { num } = strToNumNode({ str }).outputs; - return board({ inputs: { str }, outputs: { num } }); -})(); - -test("can pass board path string", () => { - const { result } = nodeThatTakesBoard({ board: "local.bgl.json" }).outputs; - const boardDef = board({ inputs: {}, outputs: { result } }); - assert.deepEqual(serialize(boardDef), { - edges: [ - { - from: "boardnode-0", - in: "result", - out: "result", - to: "output-0", - }, - ], - nodes: [ - { - configuration: { - schema: { - properties: { - result: { - type: [ - "array", - "boolean", - "null", - "number", - "object", - "string", - ], - }, - }, - required: ["result"], - type: "object", - }, - }, - id: "output-0", - type: "output", - }, - { - configuration: { - board: "local.bgl.json", - }, - id: "boardnode-0", - type: "boardnode", - }, - ], - }); -}); - -test("can pass nested board", () => { - const { result: result1 } = nodeThatTakesBoard({ - board: nestedBoard, - }).outputs; - const { result: result2 } = nodeThatTakesBoard({ - board: nestedBoard, - }).outputs; - const boardDef = board({ inputs: {}, outputs: { result1, result2 } }); - const serialized = serialize(boardDef); - assert.deepEqual(serialized, { - edges: [ - { from: "boardnode-0", to: "output-0", out: "result", in: "result1" }, - { from: "boardnode-1", to: "output-0", out: "result", in: "result2" }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - result1: { - type: [ - "array", - "boolean", - "null", - "number", - "object", - "string", - ], - }, - result2: { - type: [ - "array", - "boolean", - "null", - "number", - "object", - "string", - ], - }, - }, - required: ["result1", "result2"], - }, - }, - }, - { - id: "boardnode-0", - type: "boardnode", - configuration: { - board: { - kind: "board", - path: "#subgraph-0", - }, - }, - }, - { - id: "boardnode-1", - type: "boardnode", - configuration: { - board: { - kind: "board", - path: "#subgraph-1", - }, - }, - }, - ], - graphs: { - "subgraph-0": { - edges: [ - { from: "input-0", to: "str2num-0", out: "str", in: "str" }, - { from: "str2num-0", to: "output-0", out: "num", in: "num" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { str: { type: "string" } }, - required: ["str"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { num: { type: "number" } }, - required: ["num"], - }, - }, - }, - { id: "str2num-0", type: "str2num", configuration: {} }, - ], - }, - "subgraph-1": { - edges: [ - { from: "input-0", to: "str2num-0", out: "str", in: "str" }, - { from: "str2num-0", to: "output-0", out: "num", in: "num" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { str: { type: "string" } }, - required: ["str"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { num: { type: "number" } }, - required: ["num"], - }, - }, - }, - { id: "str2num-0", type: "str2num", configuration: {} }, - ], - }, - }, - }); -}); - -test("error passing invalid types as boards", () => { - // @ts-expect-error - nodeThatTakesBoard({ board: 123 }); - - // @ts-expect-error - nodeThatTakesBoard({ board: ["local.bgl.json"] }); -}); diff --git a/packages/build/src/test/output_test.ts b/packages/build/src/test/output_test.ts deleted file mode 100644 index 2c0647c60bd..00000000000 --- a/packages/build/src/test/output_test.ts +++ /dev/null @@ -1,355 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { board, outputNode } from "../internal/board/board.js"; -import { output } from "../internal/board/output.js"; -import { defineNodeType } from "../internal/define/define.js"; -import { anyOf } from "../internal/type-system/any-of.js"; -import { serialize } from "../internal/board/serialize.js"; -import { input } from "../internal/board/input.js"; - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -test("output usage", () => { - const strNode = defineNodeType({ - name: "foo", - inputs: { foo: { type: "string", primary: true } }, - outputs: { foo: { type: "string", primary: true } }, - invoke: () => ({ foo: "foo" }), - })({ foo: "foo" }); - - // $ExpectType Output - output(strNode); - // $ExpectType Output - output(strNode, { id: "foo" }); - // $ExpectType Output - output(strNode.outputs.foo, { id: "foo" }); - // $ExpectType Output - output(strNode.outputs.foo, { - id: "foo", - title: "My Title", - description: "My Description", - }); - - const numNode = defineNodeType({ - name: "bar", - inputs: { bar: { type: "number", primary: true } }, - outputs: { bar: { type: "number", primary: true } }, - invoke: () => ({ bar: 123 }), - })({ bar: 123 }); - - // $ExpectType Output - output(numNode); - // $ExpectType Output - output(numNode, { id: "bar" }); - // $ExpectType Output - output(numNode.outputs.bar, { id: "bar" }); - // $ExpectType Output - output(numNode.outputs.bar, { - id: "bar", - title: "My Title", - description: "My Description", - }); - - const multiNode = defineNodeType({ - name: "multi", - inputs: { - str: { type: "string" }, - num: { type: "number" }, - }, - outputs: { - str: { type: "string", primary: true }, - num: { type: "number" }, - }, - invoke: () => ({ str: "foo", num: 123 }), - })({ str: "foo", num: 123 }); - - // $ExpectType Output - output(multiNode); - // $ExpectType Output - output(multiNode, { id: "bar" }); - // $ExpectType Output - output(multiNode.outputs.str, { id: "bar" }); - // $ExpectType Output - output(multiNode.outputs.str, { - id: "bar", - title: "My Title", - description: "My Description", - }); - // $ExpectType Output - output(multiNode.outputs.num, { id: "bar" }); - // $ExpectType Output - output(multiNode.outputs.num, { - id: "bar", - title: "My Title", - description: "My Description", - }); - - // @ts-expect-error - output(); - - // $ExpectType Output - output(null, { id: "foo" }); - - output(strNode, { - // @ts-expect-error - id: 123, - }); - - output(strNode, { - // @ts-expect-error - title: 123, - }); - - output(strNode, { - // @ts-expect-error - description: 123, - }); - - output(strNode, { - // @ts-expect-error - unknown: 123, - }); - - output(strNode, { - // @ts-expect-error - id: null, - }); - - output( - // @ts-expect-error - strNode.outputs, - { id: "foo" } - ); - - output( - // @ts-expect-error - strNode.inputs, - { id: "foo" } - ); - - output( - // @ts-expect-error - strNode.inputs.foo, - { id: "foo" } - ); -}); - -test("multi-output", () => { - const { foo, bar, baz } = defineNodeType({ - name: "test", - inputs: {}, - outputs: { - foo: { type: "string" }, - bar: { type: "number" }, - baz: { type: "boolean" }, - }, - invoke: () => ({ - foo: "foo", - bar: 123, - baz: true, - }), - })({}).outputs; - - { - // $ExpectType BoardDefinition<{}, { foo: string; bar: number; mix: string; } | { bar: number; baz: boolean; mix: number; }> - const boardDef = board({ - inputs: {}, - outputs: [ - outputNode({ - foo, - bar, - mix: foo, - }), - outputNode( - { - bar, - baz, - mix: bar, - }, - { - id: "custom-output-name", - title: "Custom Title", - description: "Custom Description", - } - ), - ], - }); - - assert.deepEqual(serialize(boardDef), { - edges: [ - { from: "test-0", to: "custom-output-name", out: "bar", in: "bar" }, - { from: "test-0", to: "custom-output-name", out: "bar", in: "mix" }, - { from: "test-0", to: "custom-output-name", out: "baz", in: "baz" }, - { from: "test-0", to: "output-0", out: "bar", in: "bar" }, - { from: "test-0", to: "output-0", out: "foo", in: "foo" }, - { from: "test-0", to: "output-0", out: "foo", in: "mix" }, - ], - nodes: [ - { - id: "custom-output-name", - metadata: { - description: "Custom Description", - title: "Custom Title", - }, - type: "output", - configuration: { - schema: { - type: "object", - properties: { - bar: { type: "number" }, - baz: { type: "boolean" }, - mix: { type: "number" }, - }, - required: ["bar", "baz", "mix"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - bar: { type: "number" }, - foo: { type: "string" }, - mix: { type: "string" }, - }, - required: ["bar", "foo", "mix"], - }, - }, - }, - { id: "test-0", type: "test", configuration: {} }, - ], - }); - - { - // $ExpectType BoardInstance<{}, { foo: string; bar: number; mix: string; } | { bar: number; baz: boolean; mix: number; }> - const boardInst = boardDef({}); - - // $ExpectType { foo: Value; bar: Value; mix: Value; baz: Value; } - boardInst.outputs; - - const { - // $ExpectType Value - foo, - // $ExpectType Value - bar, - // $ExpectType Value - baz, - // $ExpectType Value - mix, - } = boardInst.outputs; - - defineNodeType({ - name: "test", - inputs: { - foo: { type: "string", optional: true }, - bar: { type: "number" }, - baz: { type: "boolean", optional: true }, - mix: { type: anyOf("string", "number") }, - }, - outputs: {}, - invoke: () => ({}), - })({ - foo, - bar, - baz, - mix, - }); - } - } -}); - -test("bubbling output node", () => { - const foo = input(); - // $ExpectType OutputNode<{ foo: string; }> - const bar = outputNode({ foo }, { bubble: true }); - const bgl = serialize(board({ inputs: { foo }, outputs: [bar] })); - assert.deepEqual(bgl, { - edges: [ - { - from: "input-0", - in: "foo", - out: "foo", - to: "output-0", - }, - ], - nodes: [ - { - configuration: { - schema: { - properties: { - foo: { - type: "string", - }, - }, - required: ["foo"], - type: "object", - }, - }, - id: "input-0", - type: "input", - }, - { - configuration: { - schema: { - behavior: ["bubble"], - properties: { - foo: { - type: "string", - }, - }, - required: ["foo"], - type: "object", - }, - }, - id: "output-0", - metadata: {}, - type: "output", - }, - ], - }); -}); - -test("deprecated output port", () => { - const foo = input(); - // $ExpectType Output - const bar = output(foo, { deprecated: true }); - const bgl = serialize(board({ inputs: { foo }, outputs: { bar } })); - assert.deepEqual(bgl, { - edges: [{ from: "input-0", to: "output-0", out: "foo", in: "bar" }], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { foo: { type: "string" } }, - required: ["foo"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - bar: { type: "string", behavior: ["deprecated"] }, - }, - required: ["bar"], - }, - }, - }, - ], - }); -}); diff --git a/packages/build/src/test/serialize_test.ts b/packages/build/src/test/serialize_test.ts deleted file mode 100644 index cb1269d4b50..00000000000 --- a/packages/build/src/test/serialize_test.ts +++ /dev/null @@ -1,2277 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -import type { GraphDescriptor } from "@google-labs/breadboard"; -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { - anyOf, - array, - defineNodeType, - object, - optionalEdge, - output, - unsafeCast, - type SerializableBoard, -} from "../index.js"; -import { board, outputNode } from "../internal/board/board.js"; -import { constant } from "../internal/board/constant.js"; -import { input } from "../internal/board/input.js"; -import { loopback } from "../internal/board/loopback.js"; -import { serialize } from "../internal/board/serialize.js"; - -function checkSerialization( - board: SerializableBoard, - expected: GraphDescriptor -) { - const actual = serialize(board); - if (JSON.stringify(actual) !== JSON.stringify(expected)) { - console.log( - `\nActual:\n==========\n` + JSON.stringify(actual) + `\n==========\n` - ); - } - assert.deepEqual(actual, expected); - // Additionally check that the order of properties is what we expect. Having - // deterministic string serialization is a nice property to have. - assert.equal(JSON.stringify(actual), JSON.stringify(expected)); -} - -test("0 inputs, 1 output", () => { - const myNode = defineNodeType({ - name: "myNode", - inputs: {}, - outputs: { - myNodeOut: { type: "string" }, - }, - invoke: () => ({ myNodeOut: "aaa" }), - })({}); - checkSerialization( - board({ - inputs: {}, - outputs: { boardOut: myNode.outputs.myNodeOut }, - }), - { - edges: [ - { from: "myNode-0", to: "output-0", out: "myNodeOut", in: "boardOut" }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { type: "string" }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: {}, - }, - ], - } - ); -}); - -test("monomorphic node with primary output can itself act as that output", () => { - const myNode = defineNodeType({ - name: "myNode", - inputs: {}, - outputs: { - myNodeOutPrimary: { type: "string", primary: true }, - }, - invoke: () => ({ myNodeOutPrimary: "aaa" }), - })({}); - checkSerialization( - board({ - inputs: {}, - outputs: { boardOut: myNode }, - }), - { - edges: [ - { - from: "myNode-0", - to: "output-0", - out: "myNodeOutPrimary", - in: "boardOut", - }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { type: "string" }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: {}, - }, - ], - } - ); -}); - -test("polymorphic node with primary output can itself act as that output", () => { - const myNode = defineNodeType({ - name: "myNode", - inputs: { - "*": { - type: "number", - }, - }, - outputs: { - myNodeOutPrimary: { type: "string", primary: true }, - }, - invoke: () => ({ myNodeOutPrimary: "aaa" }), - })({}); - checkSerialization( - board({ - inputs: {}, - outputs: { boardOut: myNode }, - }), - { - edges: [ - { - from: "myNode-0", - to: "output-0", - out: "myNodeOutPrimary", - in: "boardOut", - }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { type: "string" }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: {}, - }, - ], - } - ); -}); - -test("raw value input is serialized to configuration", () => { - const myNode = defineNodeType({ - name: "myNode", - inputs: { - myNodeIn: { type: "string" }, - }, - outputs: { - myNodeOut: { type: "string" }, - }, - invoke: () => ({ myNodeOut: "aaa" }), - })({ - myNodeIn: "bbb", - }); - checkSerialization( - board({ inputs: {}, outputs: { boardOut: myNode.outputs.myNodeOut } }), - { - edges: [ - { from: "myNode-0", to: "output-0", out: "myNodeOut", in: "boardOut" }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { boardOut: { type: "string" } }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: { - myNodeIn: "bbb", - // ^^^^^ here it is - }, - }, - ], - } - ); -}); - -test("default value input is omitted from configuration", () => { - const d = defineNodeType({ - name: "myNode", - inputs: { - required: { type: "string" }, - optional: { type: "string", default: "foo" }, - }, - outputs: { - out: { type: "string" }, - }, - invoke: () => ({ out: "foo" }), - }); - - checkSerialization( - board({ - inputs: {}, - outputs: { - boardOut: d({ - required: "foo", - }).outputs.out, - }, - }), - { - edges: [{ from: "myNode-0", to: "output-0", out: "out", in: "boardOut" }], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { type: "string" }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: { - required: "foo", - }, - }, - ], - } - ); - - checkSerialization( - board({ - inputs: {}, - outputs: { - boardOut: d({ - required: "foo", - optional: "bar", - }).outputs.out, - }, - }), - { - edges: [{ from: "myNode-0", to: "output-0", out: "out", in: "boardOut" }], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { type: "string" }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: { - optional: "bar", - required: "foo", - }, - }, - ], - } - ); -}); - -test("input", () => { - const myInput = input(); - const myNode = defineNodeType({ - name: "myNode", - inputs: { - myNodeIn: { type: "string" }, - }, - outputs: { - myNodeOut: { type: "string" }, - }, - invoke: () => ({ myNodeOut: "aaa" }), - })({ - myNodeIn: myInput, - }); - checkSerialization( - board({ - inputs: { myInput }, - outputs: { boardOut: myNode.outputs.myNodeOut }, - }), - { - edges: [ - { from: "input-0", to: "myNode-0", out: "myInput", in: "myNodeIn" }, - { from: "myNode-0", to: "output-0", out: "myNodeOut", in: "boardOut" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - myInput: { type: "string" }, - }, - required: ["myInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { type: "string" }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: {}, - }, - ], - } - ); -}); - -test("input with default", () => { - const myInput = input({ default: "ccc" }); - const myNode = defineNodeType({ - name: "myNode", - inputs: { - myNodeIn: { type: "string" }, - }, - outputs: { - myNodeOut: { type: "string" }, - }, - invoke: () => ({ myNodeOut: "aaa" }), - })({ - myNodeIn: myInput, - }); - checkSerialization( - board({ - inputs: { myInput }, - outputs: { boardOut: myNode.outputs.myNodeOut }, - }), - { - edges: [ - { from: "input-0", to: "myNode-0", out: "myInput", in: "myNodeIn" }, - { from: "myNode-0", to: "output-0", out: "myNodeOut", in: "boardOut" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - myInput: { - type: "string", - default: "ccc", - // ^^^^^ here it is! - }, - }, - required: [], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { type: "string" }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: {}, - }, - ], - } - ); -}); - -test("input with examples", () => { - const myInput = input({ examples: ["example 1", "example 2"] }); - const myNode = defineNodeType({ - name: "myNode", - inputs: { - myNodeIn: { type: "string" }, - }, - outputs: { - myNodeOut: { type: "string" }, - }, - invoke: () => ({ myNodeOut: "aaa" }), - })({ - myNodeIn: myInput, - }); - checkSerialization( - board({ - inputs: { myInput }, - outputs: { boardOut: myNode.outputs.myNodeOut }, - }), - { - edges: [ - { from: "input-0", to: "myNode-0", out: "myInput", in: "myNodeIn" }, - { from: "myNode-0", to: "output-0", out: "myNodeOut", in: "boardOut" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - myInput: { - type: "string", - examples: ["example 1", "example 2"], - // ^^^^^^^^^^^^^^^^^^^^^^^^^^ here it is! - }, - }, - required: ["myInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { type: "string" }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: {}, - }, - ], - } - ); -}); - -test("input with title and description", () => { - const myInput = input({ - title: "This is my title", - description: "This is my description", - }); - const myNode = defineNodeType({ - name: "myNode", - inputs: { - myNodeIn: { type: "string" }, - }, - outputs: { - myNodeOut: { type: "string" }, - }, - invoke: () => ({ myNodeOut: "aaa" }), - })({ - myNodeIn: myInput, - }); - checkSerialization( - board({ - inputs: { myInput }, - outputs: { boardOut: myNode.outputs.myNodeOut }, - }), - { - edges: [ - { from: "input-0", to: "myNode-0", out: "myInput", in: "myNodeIn" }, - { from: "myNode-0", to: "output-0", out: "myNodeOut", in: "boardOut" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - myInput: { - type: "string", - title: "This is my title", - description: "This is my description", - }, - }, - required: ["myInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { type: "string" }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: {}, - }, - ], - } - ); -}); - -test("fancy types", () => { - const fancyType1 = anyOf("number", object({ foo: "boolean" })); - const fancyType2 = array(anyOf("string", object({ foo: "number" }))); - const fancyType3 = object({ foo: anyOf("string", array("boolean")) }); - const myInput1 = input({ type: fancyType1 }); - const myNode = defineNodeType({ - name: "myNode", - inputs: { - myNodeIn1: { type: fancyType1 }, - myNodeIn2: { type: fancyType2 }, - }, - outputs: { - myNodeOut: { type: fancyType3 }, - }, - invoke: () => ({ myNodeOut: { foo: [true, false] } }), - })({ - myNodeIn1: myInput1, - myNodeIn2: ["aaa", { foo: 123 }], - }); - checkSerialization( - board({ - inputs: { boardInput1: myInput1 }, - outputs: { boardOut: myNode.outputs.myNodeOut }, - }), - { - edges: [ - { - from: "input-0", - to: "myNode-0", - out: "boardInput1", - in: "myNodeIn1", - }, - { - from: "myNode-0", - to: "output-0", - out: "myNodeOut", - in: "boardOut", - }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - boardInput1: { - anyOf: [ - { type: "number" }, - { - type: "object", - properties: { foo: { type: "boolean" } }, - required: ["foo"], - additionalProperties: false, - }, - ], - }, - }, - required: ["boardInput1"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { - type: "object", - properties: { - foo: { - anyOf: [ - { type: "string" }, - { type: "array", items: { type: "boolean" } }, - ], - }, - }, - required: ["foo"], - additionalProperties: false, - }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: { - myNodeIn2: ["aaa", { foo: 123 }], - }, - }, - ], - } - ); -}); - -test("long chain", () => { - const numInput = input({ type: "number" }); - - const numToString = defineNodeType({ - name: "numToString", - inputs: { - in: { type: "number" }, - }, - outputs: { - out: { type: "string", primary: true }, - }, - invoke: () => ({ out: "aaa" }), - })({ - in: numInput, - }); - - const stringToBool = defineNodeType({ - name: "stringToBool", - inputs: { - in: { type: "string" }, - }, - outputs: { - out: { type: "boolean", primary: true }, - }, - invoke: () => ({ out: true }), - })({ - in: numToString, - }); - - const boolToStringArray = defineNodeType({ - name: "boolToStringArray", - inputs: { - in: { type: "boolean" }, - }, - outputs: { - out: { type: array("string"), primary: true }, - }, - invoke: () => ({ out: ["aaa", "bbb"] }), - })({ - in: stringToBool, - }); - - checkSerialization( - board({ - inputs: { boardNumInput: numInput }, - outputs: { boardStringArrayOut: boolToStringArray }, - }), - { - edges: [ - { - from: "boolToStringArray-0", - to: "output-0", - out: "out", - in: "boardStringArrayOut", - }, - { - from: "input-0", - to: "numToString-0", - out: "boardNumInput", - in: "in", - }, - { from: "numToString-0", to: "stringToBool-0", out: "out", in: "in" }, - { - from: "stringToBool-0", - to: "boolToStringArray-0", - out: "out", - in: "in", - }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { boardNumInput: { type: "number" } }, - required: ["boardNumInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardStringArrayOut: { - type: "array", - items: { type: "string" }, - }, - }, - required: ["boardStringArrayOut"], - }, - }, - }, - { - id: "boolToStringArray-0", - type: "boolToStringArray", - configuration: {}, - }, - { - id: "numToString-0", - type: "numToString", - configuration: {}, - }, - { - id: "stringToBool-0", - type: "stringToBool", - configuration: {}, - }, - ], - } - ); -}); - -test("triangle", () => { - const aDef = defineNodeType({ - name: "a", - inputs: {}, - outputs: { - aOut1: { type: "number" }, - aOut2: { type: "number" }, - }, - invoke: () => ({ aOut1: 123, aOut2: 123 }), - }); - - const bDef = defineNodeType({ - name: "b", - inputs: { - bIn: { type: "number" }, - }, - outputs: { - bOut: { type: "number", primary: true }, - }, - invoke: () => ({ bOut: 123 }), - }); - - const a = aDef({}); - const b1 = bDef({ bIn: a.outputs.aOut2 }); - const b2 = bDef({ bIn: a.outputs.aOut1 }); - - checkSerialization( - board({ - inputs: {}, - outputs: { b1, b2 }, - }), - { - edges: [ - { from: "a-0", to: "b-0", out: "aOut2", in: "bIn" }, - { from: "a-0", to: "b-1", out: "aOut1", in: "bIn" }, - { from: "b-0", to: "output-0", out: "bOut", in: "b1" }, - { from: "b-1", to: "output-0", out: "bOut", in: "b2" }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - b1: { type: "number" }, - b2: { type: "number" }, - }, - required: ["b1", "b2"], - }, - }, - }, - { id: "a-0", type: "a", configuration: {} }, - { id: "b-0", type: "b", configuration: {} }, - { id: "b-1", type: "b", configuration: {} }, - ], - } - ); -}); - -test("polymorphic inputs", () => { - const bInput = input({ type: "number" }); - const myNode = defineNodeType({ - name: "myNode", - inputs: { - "*": { - type: "number", - }, - }, - outputs: { - out: { type: "number" }, - }, - invoke: (_, values) => ({ out: Object.values(values)[0] ?? 0 }), - })({ a: 1, b: bInput, c: 3 }); - checkSerialization( - board({ - inputs: { bInput }, - outputs: { boardOut: myNode.outputs.out }, - }), - { - edges: [ - { from: "input-0", to: "myNode-0", out: "bInput", in: "b" }, - { from: "myNode-0", to: "output-0", out: "out", in: "boardOut" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - bInput: { type: "number" }, - }, - required: ["bInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { type: "number" }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: { - a: 1, - c: 3, - }, - }, - ], - } - ); -}); - -test("polymorphic outputs", () => { - const myNode = defineNodeType({ - name: "myNode", - inputs: {}, - outputs: { - "*": { type: "number" }, - }, - describe: () => ({ outputs: ["asserted"] }), - invoke: (_, values) => ({ - out: Object.values(values)[0] ?? 0, - }), - })({}); - checkSerialization( - board({ - inputs: {}, - outputs: { - boardOut1: myNode.unsafeOutput("asserted1"), - boardOut2: myNode.unsafeOutput("asserted2"), - boardOut3: myNode.unsafeOutput("asserted1"), - }, - }), - { - edges: [ - { from: "myNode-0", to: "output-0", out: "asserted1", in: "boardOut1" }, - { from: "myNode-0", to: "output-0", out: "asserted1", in: "boardOut3" }, - { from: "myNode-0", to: "output-0", out: "asserted2", in: "boardOut2" }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut1: { type: "number" }, - boardOut2: { type: "number" }, - boardOut3: { type: "number" }, - }, - required: ["boardOut1", "boardOut2", "boardOut3"], - }, - }, - }, - { id: "myNode-0", type: "myNode", configuration: {} }, - ], - } - ); -}); - -test("loopback", () => { - const def = defineNodeType({ - name: "myNode", - inputs: { - foo: { type: "string" }, - }, - outputs: { - bar: { type: "string" }, - }, - invoke: () => ({ bar: "abc" }), - }); - - const node1Bar = loopback(); - const nodeA = def({ foo: node1Bar }); - const nodeB = def({ foo: nodeA.outputs.bar }); - node1Bar.resolve(nodeB.outputs.bar); - - checkSerialization( - board({ - inputs: {}, - outputs: { - outA: nodeA.outputs.bar, - outB: nodeB.outputs.bar, - }, - }), - { - edges: [ - { from: "myNode-0", to: "myNode-1", out: "bar", in: "foo" }, - { from: "myNode-0", to: "output-0", out: "bar", in: "outA" }, - { from: "myNode-1", to: "myNode-0", out: "bar", in: "foo" }, - { from: "myNode-1", to: "output-0", out: "bar", in: "outB" }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - outA: { type: "string" }, - outB: { type: "string" }, - }, - required: ["outA", "outB"], - }, - }, - }, - { id: "myNode-0", type: "myNode", configuration: {} }, - { id: "myNode-1", type: "myNode", configuration: {} }, - ], - } - ); -}); - -test("error: loopback not resolved", () => { - const def = defineNodeType({ - name: "myNode", - inputs: { - foo: { type: "string" }, - }, - outputs: { - bar: { type: "string" }, - }, - invoke: () => ({ bar: "abc" }), - }); - - const node1Bar = loopback(); - const nodeA = def({ foo: node1Bar }); - const nodeB = def({ foo: nodeA.outputs.bar }); - - assert.throws( - () => - serialize( - board({ - inputs: {}, - outputs: { - outA: nodeA.outputs.bar, - outB: nodeB.outputs.bar, - }, - }) - ), - /Loopback was never resolved/ - ); -}); - -test("error: input not passed to board", () => { - const myInput = input(); - const myNode = defineNodeType({ - name: "myNode", - inputs: { - myNodeIn: { type: "string" }, - }, - outputs: { - myNodeOut: { type: "string" }, - }, - invoke: () => ({ myNodeOut: "aaa" }), - })({ - myNodeIn: myInput, - }); - assert.throws( - () => - serialize( - board({ - inputs: {}, - outputs: { - boardOut: myNode.outputs.myNodeOut, - }, - }) - ), - /myNode-0:myNodeIn was wired to an input, but that input was not provided to the board inputs./ - ); -}); - -test("error: input not reachable from output", () => { - const myInput = input(); - const myOrphanInput = input(); - const myNode = defineNodeType({ - name: "myNode", - inputs: { - myNodeIn: { type: "string" }, - }, - outputs: { - myNodeOut: { type: "string" }, - }, - invoke: () => ({ myNodeOut: "aaa" }), - })({ - myNodeIn: myInput, - }); - assert.throws( - () => - serialize( - board({ - inputs: { boardInput1: myInput, boardInput2: myOrphanInput }, - outputs: { boardOut: myNode.outputs.myNodeOut }, - }) - ), - /Board input "boardInput2" is not reachable from any of its outputs./ - ); -}); - -test("board title, description, and version", () => { - const foo = defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - foo: { type: "string", primary: true }, - }, - invoke: () => ({ foo: "foo" }), - })({}); - checkSerialization( - board({ - title: "Board Name", - description: "Board Description", - version: "1.2.3", - inputs: {}, - outputs: { foo }, - }), - { - title: "Board Name", - description: "Board Description", - version: "1.2.3", - edges: [{ from: "foo-0", to: "output-0", out: "foo", in: "foo" }], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { foo: { type: "string" } }, - required: ["foo"], - }, - }, - }, - { id: "foo-0", type: "foo", configuration: {} }, - ], - } - ); -}); - -test("icon", () => { - const foo = defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - foo: { type: "string", primary: true }, - }, - invoke: () => ({ foo: "foo" }), - })({}); - checkSerialization( - board({ - title: "Board Name", - description: "Board Description", - version: "1.2.3", - metadata: { - icon: "potato", - }, - inputs: {}, - outputs: { foo }, - }), - { - title: "Board Name", - description: "Board Description", - version: "1.2.3", - metadata: { - icon: "potato", - }, - edges: [{ from: "foo-0", to: "output-0", out: "foo", in: "foo" }], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { foo: { type: "string" } }, - required: ["foo"], - }, - }, - }, - { id: "foo-0", type: "foo", configuration: {} }, - ], - } - ); -}); - -test("node can have IDs", () => { - const d1 = defineNodeType({ - name: "d1", - inputs: {}, - outputs: { - foo: { type: "string", primary: true }, - }, - invoke: () => ({ foo: "foo" }), - }); - - const d2 = defineNodeType({ - name: "d2", - inputs: { - bar: { type: "string" }, - }, - outputs: { - baz: { type: "string", primary: true }, - }, - invoke: () => ({ baz: "baz" }), - }); - - const i1 = d1({ $id: "myCustomId1" }); - const i2 = d2({ $id: "myCustomId2", bar: i1 }); - const b = board({ inputs: {}, outputs: { i2 } }); - - checkSerialization(b, { - edges: [ - { from: "myCustomId1", to: "myCustomId2", out: "foo", in: "bar" }, - { from: "myCustomId2", to: "output-0", out: "baz", in: "i2" }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { i2: { type: "string" } }, - required: ["i2"], - }, - }, - }, - { id: "myCustomId1", type: "d1", configuration: {} }, - { id: "myCustomId2", type: "d2", configuration: {} }, - ], - }); -}); - -test("node can have metadata", () => { - const d1 = defineNodeType({ - name: "d1", - inputs: {}, - outputs: { - foo: { type: "string", primary: true }, - }, - invoke: () => ({ foo: "foo" }), - }); - - const d2 = defineNodeType({ - name: "d2", - inputs: { - bar: { type: "string" }, - }, - outputs: { - baz: { type: "string", primary: true }, - }, - invoke: () => ({ baz: "baz" }), - }); - - const i1 = d1({ - $id: "myCustomId1", - $metadata: { - title: "my custom title 1", - logLevel: "info", - }, - }); - const i2 = d2({ - $id: "myCustomId2", - bar: i1, - $metadata: { - title: "my custom title 2", - description: "my custom description 2", - }, - }); - const b = board({ inputs: {}, outputs: { i2 } }); - - checkSerialization(b, { - edges: [ - { from: "myCustomId1", to: "myCustomId2", out: "foo", in: "bar" }, - { from: "myCustomId2", to: "output-0", out: "baz", in: "i2" }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { i2: { type: "string" } }, - required: ["i2"], - }, - }, - }, - { - id: "myCustomId1", - type: "d1", - configuration: {}, - metadata: { - title: "my custom title 1", - logLevel: "info", - }, - }, - { - id: "myCustomId2", - type: "d2", - configuration: {}, - metadata: { - title: "my custom title 2", - description: "my custom description 2", - }, - }, - ], - }); -}); - -test("can't declare an input port called $metadata because it's reserved", () => { - assert.throws(() => { - const def = defineNodeType({ - name: "d1", - inputs: { - // @ts-expect-error - $metadata: { - type: "string", - }, - }, - outputs: { - foo: { type: "string", primary: true }, - }, - invoke: () => ({ foo: "foo" }), - }); - def({}); - }, /"\$metadata" cannot be used as an input port name because it is reserved/); -}); - -test("custom input id", () => { - const passthru = defineNodeType({ - name: "passthru", - inputs: { - value: { type: "string" }, - }, - outputs: { - value: { type: "string", primary: true }, - }, - invoke: ({ value }) => ({ value }), - }); - - const in1 = input({ $id: "custom-input" }); - - checkSerialization( - board({ - inputs: { - in1, - }, - outputs: { - result: passthru({ value: in1 }), - }, - }), - { - edges: [ - { from: "custom-input", to: "passthru-0", out: "in1", in: "value" }, - { from: "passthru-0", to: "output-0", out: "value", in: "result" }, - ], - nodes: [ - { - id: "custom-input", - type: "input", - configuration: { - schema: { - type: "object", - properties: { in1: { type: "string" } }, - required: ["in1"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { result: { type: "string" } }, - required: ["result"], - }, - }, - }, - { id: "passthru-0", type: "passthru", configuration: {} }, - ], - } - ); -}); - -test("two different custom input ids", () => { - const passthru = defineNodeType({ - name: "passthru", - inputs: { - value1: { type: "string" }, - value2: { type: "string" }, - }, - outputs: { - value1: { type: "string" }, - value2: { type: "string" }, - }, - invoke: ({ value1, value2 }) => ({ value1, value2 }), - }); - - const in1 = input({ $id: "custom-input-1" }); - const in2 = input({ $id: "custom-input-2" }); - const pt = passthru({ value1: in1, value2: in2 }); - - checkSerialization( - board({ - inputs: { - in1, - in2, - }, - outputs: { - result1: pt.outputs.value1, - result2: pt.outputs.value2, - }, - }), - { - edges: [ - { from: "custom-input-1", to: "passthru-0", out: "in1", in: "value1" }, - { from: "custom-input-2", to: "passthru-0", out: "in2", in: "value2" }, - { from: "passthru-0", to: "output-0", out: "value1", in: "result1" }, - { from: "passthru-0", to: "output-0", out: "value2", in: "result2" }, - ], - nodes: [ - { - id: "custom-input-1", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - in1: { type: "string" }, - }, - required: ["in1"], - }, - }, - }, - { - id: "custom-input-2", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - in2: { type: "string" }, - }, - required: ["in2"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - result1: { type: "string" }, - result2: { type: "string" }, - }, - required: ["result1", "result2"], - }, - }, - }, - { id: "passthru-0", type: "passthru", configuration: {} }, - ], - } - ); -}); - -test("two same custom input ids", () => { - const passthru = defineNodeType({ - name: "passthru", - inputs: { - value1: { type: "string" }, - value2: { type: "string" }, - }, - outputs: { - value1: { type: "string" }, - value2: { type: "string" }, - }, - invoke: ({ value1, value2 }) => ({ value1, value2 }), - }); - - const in1 = input({ $id: "custom-input" }); - const in2 = input({ $id: "custom-input" }); - const pt = passthru({ value1: in1, value2: in2 }); - - checkSerialization( - board({ - inputs: { - in1, - in2, - }, - outputs: { - result1: pt.outputs.value1, - result2: pt.outputs.value2, - }, - }), - { - edges: [ - { from: "custom-input", to: "passthru-0", out: "in1", in: "value1" }, - { from: "custom-input", to: "passthru-0", out: "in2", in: "value2" }, - { from: "passthru-0", to: "output-0", out: "value1", in: "result1" }, - { from: "passthru-0", to: "output-0", out: "value2", in: "result2" }, - ], - nodes: [ - { - id: "custom-input", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - in1: { type: "string" }, - in2: { type: "string" }, - }, - required: ["in1", "in2"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - result1: { type: "string" }, - result2: { type: "string" }, - }, - required: ["result1", "result2"], - }, - }, - }, - { id: "passthru-0", type: "passthru", configuration: {} }, - ], - } - ); -}); - -test("custom and default input id", () => { - const passthru = defineNodeType({ - name: "passthru", - inputs: { - value1: { type: "string" }, - value2: { type: "string" }, - }, - outputs: { - value1: { type: "string" }, - value2: { type: "string" }, - }, - invoke: ({ value1, value2 }) => ({ value1, value2 }), - }); - - const in1 = input({ $id: "custom-input" }); - const in2 = input({}); - const pt = passthru({ value1: in1, value2: in2 }); - - checkSerialization( - board({ - inputs: { - in1, - in2, - }, - outputs: { - result1: pt.outputs.value1, - result2: pt.outputs.value2, - }, - }), - { - edges: [ - { from: "custom-input", to: "passthru-0", out: "in1", in: "value1" }, - { from: "input-0", to: "passthru-0", out: "in2", in: "value2" }, - { from: "passthru-0", to: "output-0", out: "value1", in: "result1" }, - { from: "passthru-0", to: "output-0", out: "value2", in: "result2" }, - ], - nodes: [ - { - id: "custom-input", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - in1: { type: "string" }, - }, - required: ["in1"], - }, - }, - }, - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - in2: { type: "string" }, - }, - required: ["in2"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - result1: { type: "string" }, - result2: { type: "string" }, - }, - required: ["result1", "result2"], - }, - }, - }, - { id: "passthru-0", type: "passthru", configuration: {} }, - ], - } - ); -}); - -test("custom output id", () => { - const def = defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - value: { type: "string", primary: true }, - }, - invoke: () => ({ value: "foo" }), - }); - - checkSerialization( - board({ - inputs: {}, - outputs: { - result: output(def({}), { id: "custom-output" }), - }, - }), - { - edges: [ - { from: "foo-0", to: "custom-output", out: "value", in: "result" }, - ], - nodes: [ - { - id: "custom-output", - type: "output", - configuration: { - schema: { - type: "object", - properties: { result: { type: "string" } }, - required: ["result"], - }, - }, - }, - { id: "foo-0", type: "foo", configuration: {} }, - ], - } - ); -}); - -test("two different custom output ids", () => { - const def = defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - value1: { type: "string" }, - value2: { type: "string" }, - }, - invoke: () => ({ value1: "foo", value2: "foo" }), - }); - - const foo = def({}); - - checkSerialization( - board({ - inputs: {}, - outputs: { - result1: output(foo.outputs.value1, { id: "custom-input-1" }), - result2: output(foo.outputs.value2, { id: "custom-input-2" }), - }, - }), - { - edges: [ - { from: "foo-0", to: "custom-input-1", out: "value1", in: "result1" }, - { from: "foo-0", to: "custom-input-2", out: "value2", in: "result2" }, - ], - nodes: [ - { - id: "custom-input-1", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - result1: { type: "string" }, - }, - required: ["result1"], - }, - }, - }, - { - id: "custom-input-2", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - result2: { type: "string" }, - }, - required: ["result2"], - }, - }, - }, - { id: "foo-0", type: "foo", configuration: {} }, - ], - } - ); -}); - -test("two same custom output ids", () => { - const def = defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - value1: { type: "string" }, - value2: { type: "string" }, - }, - invoke: () => ({ value1: "foo", value2: "foo" }), - }); - - const foo = def({}); - - checkSerialization( - board({ - inputs: {}, - outputs: { - result1: output(foo.outputs.value1, { id: "custom-output" }), - result2: output(foo.outputs.value2, { id: "custom-output" }), - }, - }), - { - edges: [ - { from: "foo-0", to: "custom-output", out: "value1", in: "result1" }, - { from: "foo-0", to: "custom-output", out: "value2", in: "result2" }, - ], - nodes: [ - { - id: "custom-output", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - result1: { type: "string" }, - result2: { type: "string" }, - }, - required: ["result1", "result2"], - }, - }, - }, - { id: "foo-0", type: "foo", configuration: {} }, - ], - } - ); -}); - -test("custom and default output ids", () => { - const def = defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - value1: { type: "string" }, - value2: { type: "string" }, - }, - invoke: () => ({ value1: "foo", value2: "foo" }), - }); - - const foo = def({}); - - checkSerialization( - board({ - inputs: {}, - outputs: { - result1: foo.outputs.value1, - result2: output(foo.outputs.value2, { id: "custom-output" }), - }, - }), - { - edges: [ - { from: "foo-0", to: "custom-output", out: "value2", in: "result2" }, - { from: "foo-0", to: "output-0", out: "value1", in: "result1" }, - ], - nodes: [ - { - id: "custom-output", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - result2: { type: "string" }, - }, - required: ["result2"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - result1: { type: "string" }, - }, - required: ["result1"], - }, - }, - }, - { id: "foo-0", type: "foo", configuration: {} }, - ], - } - ); -}); - -test("output with title and description", () => { - const myNode = defineNodeType({ - name: "myNode", - inputs: {}, - outputs: { - myNodeOut: { type: "string" }, - }, - invoke: () => ({ myNodeOut: "aaa" }), - })({}); - checkSerialization( - board({ - inputs: {}, - outputs: { - boardOut: output(myNode.outputs.myNodeOut, { - id: "custom-output", - title: "Custom Title", - description: "Custom Description", - }), - }, - }), - { - edges: [ - { - from: "myNode-0", - to: "custom-output", - out: "myNodeOut", - in: "boardOut", - }, - ], - nodes: [ - { - id: "custom-output", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { - type: "string", - title: "Custom Title", - description: "Custom Description", - }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: {}, - }, - ], - } - ); -}); - -test("unsafe cast as output", () => { - const myNode = defineNodeType({ - name: "myNode", - inputs: {}, - outputs: { - myNodeOut: { type: "string" }, - }, - invoke: () => ({ myNodeOut: "aaa" }), - })({}); - checkSerialization( - board({ - inputs: {}, - outputs: { - boardOut: output(unsafeCast(myNode.outputs.myNodeOut, "number"), { - id: "custom-output", - title: "Custom Title", - description: "Custom Description", - }), - }, - }), - { - edges: [ - { - from: "myNode-0", - to: "custom-output", - out: "myNodeOut", - in: "boardOut", - }, - ], - nodes: [ - { - id: "custom-output", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - boardOut: { - type: "number", - title: "Custom Title", - description: "Custom Description", - }, - }, - required: ["boardOut"], - }, - }, - }, - { - id: "myNode-0", - type: "myNode", - configuration: {}, - }, - ], - } - ); -}); - -test("unsafe cast as input to another node", () => { - const makesStringDef = defineNodeType({ - name: "makesString", - inputs: {}, - outputs: { - str: { type: "string", primary: true }, - }, - invoke: () => ({ str: "foo" }), - }); - - const takesNumberDef = defineNodeType({ - name: "takesNumber", - inputs: { - num: { type: "number" }, - }, - outputs: { - num: { type: "number", primary: true }, - }, - invoke: ({ num }) => ({ num }), - }); - - takesNumberDef({ - // @ts-expect-error - num: makesStringDef({}), - }); - - checkSerialization( - board({ - inputs: {}, - outputs: { - strAsNum: takesNumberDef({ - num: unsafeCast(makesStringDef({}), "number"), - }), - }, - }), - { - edges: [ - { from: "makesString-0", to: "takesNumber-0", out: "str", in: "num" }, - { from: "takesNumber-0", to: "output-0", out: "num", in: "strAsNum" }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - strAsNum: { type: "number" }, - }, - required: ["strAsNum"], - }, - }, - }, - { id: "makesString-0", type: "makesString", configuration: {} }, - { id: "takesNumber-0", type: "takesNumber", configuration: {} }, - ], - } - ); -}); - -test("constant", () => { - const a = defineNodeType({ - name: "a", - inputs: {}, - outputs: { - ao1: { type: "string", primary: true }, - ao2: { type: "number" }, - ao3: { type: "boolean" }, - }, - invoke: () => ({ ao1: "foo", ao2: 123, ao3: true }), - }); - - const b = defineNodeType({ - name: "b", - inputs: { - bi1c: { type: "string" }, - bi2: { type: "number" }, - bi3c: { type: "boolean" }, - }, - outputs: { - bo1: { type: "string", primary: true }, - bo2: { type: "number" }, - bo3: { type: "boolean" }, - }, - invoke: () => ({ bo1: "foo", bo2: 123, bo3: true }), - }); - - const { ao1, ao2, ao3 } = a({}).outputs; - const { bo1, bo2 } = b({ - bi1c: constant(ao1), - bi2: ao2, - bi3c: constant(ao3), - }).outputs; - - checkSerialization( - board({ - inputs: {}, - outputs: { - ao1, - ao2c: constant(ao2), - bo1, - bo2c: constant(bo2), - }, - }), - { - edges: [ - { from: "a-0", to: "b-0", out: "ao1", in: "bi1c", constant: true }, - { from: "a-0", to: "b-0", out: "ao2", in: "bi2" }, - { from: "a-0", to: "b-0", out: "ao3", in: "bi3c", constant: true }, - { from: "a-0", to: "output-0", out: "ao1", in: "ao1" }, - { from: "a-0", to: "output-0", out: "ao2", in: "ao2c", constant: true }, - { from: "b-0", to: "output-0", out: "bo1", in: "bo1" }, - { from: "b-0", to: "output-0", out: "bo2", in: "bo2c", constant: true }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - ao1: { type: "string" }, - ao2c: { type: "number" }, - bo1: { type: "string" }, - bo2c: { type: "number" }, - }, - required: ["ao1", "ao2c", "bo1", "bo2c"], - }, - }, - }, - { id: "a-0", type: "a", configuration: {} }, - { id: "b-0", type: "b", configuration: {} }, - ], - } - ); -}); - -test("constant input", () => { - const stringInput = input(); - const inputWithDefault = input({ default: 123 }); - - const a = defineNodeType({ - name: "a", - inputs: { - ai1: { type: "string" }, - ai2: { type: "number" }, - }, - outputs: { - ao1: { type: "string" }, - }, - invoke: () => ({ ao1: "foo" }), - }); - - const { ao1 } = a({ - ai1: constant(stringInput), - ai2: constant(inputWithDefault), - }).outputs; - - checkSerialization( - board({ - inputs: { - stringInput, - inputWithDefault, - }, - outputs: { - ao1, - }, - }), - { - edges: [ - { - from: "a-0", - to: "output-0", - out: "ao1", - in: "ao1", - }, - { - from: "input-0", - to: "a-0", - out: "inputWithDefault", - in: "ai2", - constant: true, - }, - { - from: "input-0", - to: "a-0", - out: "stringInput", - in: "ai1", - constant: true, - }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - inputWithDefault: { type: "number", default: "123" }, - stringInput: { type: "string" }, - }, - required: ["stringInput"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { ao1: { type: "string" } }, - required: ["ao1"], - }, - }, - }, - { id: "a-0", type: "a", configuration: {} }, - ], - } - ); -}); - -test("optional output", () => { - const foo = defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - nodeOut: { type: "string" }, - }, - invoke: () => ({ nodeOut: "foo" }), - }); - - const { nodeOut } = foo({}).outputs; - - checkSerialization( - board({ - inputs: {}, - outputs: { boardOut: output(optionalEdge(nodeOut)) }, - }), - { - edges: [ - { - from: "foo-0", - to: "output-0", - out: "nodeOut", - in: "boardOut", - optional: true, - }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { boardOut: { type: "string" } }, - required: [], - }, - }, - }, - { id: "foo-0", type: "foo", configuration: {} }, - ], - } - ); -}); - -test("$error can be wired to $error", () => { - const foo = defineNodeType({ - name: "foo", - inputs: {}, - outputs: { - foo: { type: "string" }, - }, - invoke: () => ({ foo: "foo" }), - })({}); - - checkSerialization( - board({ - inputs: {}, - outputs: [outputNode({ $error: output(foo.outputs.$error) })], - }), - { - edges: [{ from: "foo-0", to: "output-0", out: "$error", in: "$error" }], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - $error: { - type: "object", - anyOf: [ - { - type: "object", - properties: { message: { type: "string" } }, - required: ["message"], - additionalProperties: false, - }, - { - type: "object", - properties: { - kind: { type: "string" }, - error: { - type: "object", - properties: { message: { type: "string" } }, - required: ["message"], - additionalProperties: false, - }, - }, - required: ["kind", "error"], - additionalProperties: false, - }, - ], - }, - }, - required: ["$error"], - }, - }, - }, - { id: "foo-0", type: "foo", configuration: {} }, - ], - } - ); -}); diff --git a/packages/build/src/test/star-inputs_test.ts b/packages/build/src/test/star-inputs_test.ts deleted file mode 100644 index 22a61bcf118..00000000000 --- a/packages/build/src/test/star-inputs_test.ts +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { - array, - board, - defineNodeType, - input, - inputNode, - serialize, - starInputs, -} from "../index.js"; - -test("StarInputs type parameterization", () => { - // $ExpectType StarInputs - starInputs({ type: "string" }); - - // $ExpectType StarInputs - starInputs({ type: array("number") }); -}); - -/** - * A discrete component for testing that takes all * inputs and joins them. - */ -const lineCombiner = defineNodeType({ - name: "lineCombiner", - inputs: { "*": { type: "string" } }, - outputs: { joined: { type: "string" } }, - invoke: ({ ...lines }) => ({ - joined: Object.values(lines).join(), - }), -}); - -/** - * A discrete component for testing that takes an array of inputs and joins them - * (it doesn't have a "*" port). - */ -const nonDynamicLineCombiner = defineNodeType({ - name: "lineCombiner", - inputs: { lines: { type: array("string") } }, - outputs: { joined: { type: "string" } }, - invoke: ({ lines }) => ({ - joined: Object.values(lines).join(), - }), -}); - -test("can pass to dynamic discrete component", () => { - const lines = starInputs({ type: "string" }); - lineCombiner({ "*": lines }); -}); - -test.skip("error to pass to non-dynamic discrete component", () => { - const starLines = starInputs({ type: "string" }); - const arrayLines = input({ type: array("string") }); - nonDynamicLineCombiner({ - lines: arrayLines, - // TODO(aomarks) @ts-expect-error - "*": starLines, - }); -}); - -test.skip("error to pass wrong type to discrete component", () => { - const notLines = starInputs({ type: "number" }); - // TODO(aomarks) @ts-expect-error - lineCombiner({ "*": notLines }); -}); - -test("can pass to inputNode", () => { - const starLines = starInputs({ type: "string" }); - // $ExpectType InputNode<{ "*": string; }> - inputNode({ "*": starLines }); -}); - -test.skip("can only pass to inputNode as *", () => { - const starLines = starInputs({ type: "string" }); - // TODO(aomarks) @ts-expect-error - inputNode({ foo: starLines }); -}); - -test("can pass as board shorthand", () => { - const starLines = starInputs({ type: "string" }); - // $ExpectType BoardDefinition<{ "*": string; }, {}> - board({ inputs: { "*": starLines }, outputs: {} }); -}); - -test.skip("can only pass to board shorthand as *", () => { - const starLines = starInputs({ type: "string" }); - // TODO(aomarks) @ts-expect-error - board({ inputs: { foo: starLines }, outputs: {} }); -}); - -test("can serialize when passed to discrete component", () => { - const lines = starInputs({ type: "string" }); - const { joined } = lineCombiner({ "*": lines }).outputs; - const testBoard = board({ inputs: { "*": lines }, outputs: { joined } }); - const bgl = serialize(testBoard); - assert.deepEqual(bgl, { - edges: [ - { from: "input-0", to: "lineCombiner-0", out: "*", in: "" }, - { from: "lineCombiner-0", to: "output-0", out: "joined", in: "joined" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: {}, - required: [], - additionalProperties: { type: "string" }, - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { joined: { type: "string" } }, - required: ["joined"], - }, - }, - }, - { id: "lineCombiner-0", type: "lineCombiner", configuration: {} }, - ], - }); -}); diff --git a/packages/build/src/test/type-expressions/annotate_test.ts b/packages/build/src/test/type-expressions/annotate_test.ts deleted file mode 100644 index 4ce3ad0fbf6..00000000000 --- a/packages/build/src/test/type-expressions/annotate_test.ts +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { annotate, array, object } from "@breadboard-ai/build"; -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { toJSONSchema } from "../../internal/type-system/type.js"; - -test("can annotate a nested object with a behavior", () => { - assert.deepEqual( - toJSONSchema( - // $ExpectType AdvancedBreadboardType<{ foo: number; }[]> - array( - annotate(object({ foo: "number" }), { - behavior: ["llm-content"], - }) - ) - ), - { - type: "array", - items: { - type: "object", - properties: { - foo: { type: "number" }, - }, - required: ["foo"], - additionalProperties: false, - behavior: ["llm-content"], - }, - } - ); -}); - -test("can annotate basic type with behavior", () => { - assert.deepEqual( - toJSONSchema( - // $ExpectType "string" - annotate("string", { - behavior: ["llm-content"], - }) - ), - { - type: "string", - behavior: ["llm-content"], - } - ); -}); - -test("behaviors are additive", () => { - assert.deepEqual( - toJSONSchema( - // $ExpectType "string" - annotate( - annotate("string", { - behavior: ["llm-content", "deprecated"], - }), - { behavior: ["llm-content", "config"] } - ) - ), - { - type: "string", - behavior: ["llm-content", "deprecated", "config"], - } - ); -}); diff --git a/packages/build/src/test/type-expressions/anyof_test.ts b/packages/build/src/test/type-expressions/anyof_test.ts deleted file mode 100644 index 9d3a7938cc0..00000000000 --- a/packages/build/src/test/type-expressions/anyof_test.ts +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { anyOf, object } from "@breadboard-ai/build"; -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { - toJSONSchema, - type BreadboardType, - type ConvertBreadboardType, -} from "../../internal/type-system/type.js"; - -/* eslint-disable @typescript-eslint/no-unused-vars */ - -test("anyOf", () => { - // @ts-expect-error no arguments - anyOf(); - // @ts-expect-error only one argument - anyOf("number"); - // @ts-expect-error not a valid type - assert.throws(() => anyOf(undefined)); - // @ts-expect-error not a valid type - assert.throws(() => anyOf("xnumber", "xstring")); - - const with2 = anyOf("number", "boolean") satisfies BreadboardType; - // $ExpectType number | boolean - type t2 = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(with2), { - type: ["number", "boolean"], - }); - - const with3 = anyOf("number", "boolean", "string") satisfies BreadboardType; - // $ExpectType string | number | boolean - type t3 = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(with3), { - type: ["number", "boolean", "string"], - }); -}); - -test("hoists common type", () => { - const any = anyOf(object({}), object({})); - assert.deepEqual(toJSONSchema(any), { - type: "object", - anyOf: [ - { - additionalProperties: false, - properties: {}, - required: [], - type: "object", - }, - { - additionalProperties: false, - properties: {}, - required: [], - type: "object", - }, - ], - }); -}); diff --git a/packages/build/src/test/type-expressions/array_test.ts b/packages/build/src/test/type-expressions/array_test.ts deleted file mode 100644 index 1a6a2729fb3..00000000000 --- a/packages/build/src/test/type-expressions/array_test.ts +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { anyOf, array, object } from "@breadboard-ai/build"; -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { - toJSONSchema, - type ConvertBreadboardType, -} from "../../internal/type-system/type.js"; - -/* eslint-disable @typescript-eslint/no-unused-vars */ - -test("no arguments", () => { - // @ts-expect-error no arguments - assert.throws(() => array()); -}); - -test("array of numbers", () => { - const arr = array("number"); - // $ExpectType number[] - type arrayType = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(arr), { - type: "array", - items: { type: "number" }, - }); -}); - -test("array of objects", () => { - const arr = array(object({ foo: "string" })); - // $ExpectType { foo: string; }[] - type arrayType = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(arr), { - type: "array", - items: { - type: "object", - properties: { foo: { type: "string" } }, - required: ["foo"], - additionalProperties: false, - }, - }); -}); - -test("array of anyOf types", () => { - const arr = array(anyOf("string", "number")); - // $ExpectType (string | number)[] - type arrayType = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(arr), { - type: "array", - items: { type: ["string", "number"] }, - }); -}); - -test("array of unknown", () => { - const arr = array("unknown"); - // $ExpectType JsonSerializable[] - type arrayType = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(arr), { - items: { - type: ["array", "boolean", "null", "number", "object", "string"], - }, - type: "array", - }); -}); diff --git a/packages/build/src/test/type-expressions/basics_test.ts b/packages/build/src/test/type-expressions/basics_test.ts deleted file mode 100644 index 3219738979d..00000000000 --- a/packages/build/src/test/type-expressions/basics_test.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { - toJSONSchema, - type BreadboardType, - type ConvertBreadboardType, -} from "../../internal/type-system/type.js"; - -test("string", () => { - "string" satisfies BreadboardType; - // @ts-expect-error not a valid basic type - "xstring" satisfies BreadboardType; - assert.deepEqual(toJSONSchema("string"), { type: "string" }); - /* eslint-disable @typescript-eslint/no-unused-vars */ - // $ExpectType string - type t = ConvertBreadboardType<"string">; - /* eslint-enable @typescript-eslint/no-unused-vars */ -}); - -test("number", () => { - "number" satisfies BreadboardType; - // @ts-expect-error not a valid basic type - "xnumber" satisfies BreadboardType; - assert.deepEqual(toJSONSchema("number"), { type: "number" }); - /* eslint-disable @typescript-eslint/no-unused-vars */ - // $ExpectType number - type t = ConvertBreadboardType<"number">; - /* eslint-enable @typescript-eslint/no-unused-vars */ -}); - -test("boolean", () => { - "boolean" satisfies BreadboardType; - // @ts-expect-error not a valid basic type - "xboolean" satisfies BreadboardType; - assert.deepEqual(toJSONSchema("boolean"), { type: "boolean" }); - /* eslint-disable @typescript-eslint/no-unused-vars */ - // $ExpectType boolean - type t = ConvertBreadboardType<"boolean">; - /* eslint-enable @typescript-eslint/no-unused-vars */ -}); - -test("unknown", () => { - "unknown" satisfies BreadboardType; - // @ts-expect-error not a valid basic type - "xunknown" satisfies BreadboardType; - assert.deepEqual(toJSONSchema("unknown"), { - type: ["array", "boolean", "null", "number", "object", "string"], - }); - /* eslint-disable @typescript-eslint/no-unused-vars */ - // $ExpectType JsonSerializable - type t = ConvertBreadboardType<"unknown">; - /* eslint-enable @typescript-eslint/no-unused-vars */ -}); diff --git a/packages/build/src/test/type-expressions/intersect_test.ts b/packages/build/src/test/type-expressions/intersect_test.ts deleted file mode 100644 index 1015e3d474f..00000000000 --- a/packages/build/src/test/type-expressions/intersect_test.ts +++ /dev/null @@ -1,177 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { intersect } from "../../internal/type-system/intersect.js"; -import { object, optional } from "../../internal/type-system/object.js"; -import { - toJSONSchema, - type ConvertBreadboardType, -} from "../../internal/type-system/type.js"; -import { array } from "../../internal/type-system/array.js"; - -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -test("two disjoint closed required objects", () => { - const intersection = intersect( - object({ foo: "string" }), - object({ bar: "number" }) - ); - // $ExpectType { foo: string; } & { bar: number; } - type t = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(intersection), { - type: "object", - properties: { - foo: { - type: "string", - }, - bar: { - type: "number", - }, - }, - required: ["foo", "bar"], - additionalProperties: false, - }); -}); - -test("two disjoint closed optional objects", () => { - const intersection = intersect( - object({ foo: optional("string") }), - object({ bar: optional("number") }) - ); - // $ExpectType { foo?: string | undefined; } & { bar?: number | undefined; } - type t = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(intersection), { - type: "object", - properties: { - foo: { - type: "string", - }, - bar: { - type: "number", - }, - }, - required: [], - additionalProperties: false, - }); -}); - -test("two disjoint fully open required objects", () => { - const intersection = intersect( - object({ foo: "string" }, "unknown"), - object({ bar: "number" }, "unknown") - ); - // $ExpectType { [x: string]: JsonSerializable; foo: string; } & { [x: string]: JsonSerializable; bar: number; } - type t = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(intersection), { - type: "object", - properties: { - foo: { - type: "string", - }, - bar: { - type: "number", - }, - }, - required: ["foo", "bar"], - additionalProperties: true, - }); -}); - -test("two complex nested objects", () => { - const intersection = intersect( - object({ foo: object({ foo2: array("number") }) }), - object({ bar: object({ bar2: array("boolean") }) }) - ); - // $ExpectType { foo: { foo2: number[]; }; } & { bar: { bar2: boolean[]; }; } - type t = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(intersection), { - type: "object", - properties: { - bar: { - type: "object", - properties: { - bar2: { - items: { - type: "boolean", - }, - type: "array", - }, - }, - required: ["bar2"], - additionalProperties: false, - }, - foo: { - type: "object", - properties: { - foo2: { - items: { - type: "number", - }, - type: "array", - }, - }, - required: ["foo2"], - additionalProperties: false, - }, - }, - required: ["foo", "bar"], - additionalProperties: false, - }); -}); - -test("error: no arguments", () => { - assert.throws( - () => - // @ts-expect-error - intersect(), - /intersect requires at least 2 arguments, got 0/ - ); -}); - -test("error: one object", () => { - assert.throws( - () => - // @ts-expect-error - intersect(object({ foo: "string" })), - /intersect requires at least 2 arguments, got 1/ - ); -}); - -test("error: not an object (number)", () => { - assert.throws( - // @ts-expect-error - () => intersect(object({ foo: "string" }), "number"), - /intersect only supports objects, got number/ - ); -}); - -test("error: not an object (array)", () => { - assert.throws( - () => intersect(object({ foo: "string" }), array("number")), - /intersect only supports objects, got array/ - ); -}); - -test("error: overlapping properties", () => { - assert.throws( - () => intersect(object({ foo: "string" }), object({ foo: "number" })), - /intersect only supports disjoint properties, got "foo" 2 or more times/ - ); -}); - -test("error: partially open", () => { - assert.throws( - () => - intersect( - object({ foo: "string" }, "string"), - object({ bar: "number" }, "unknown") - ), - /intersect only supports closed or fully open objects, got {"additionalProperties":{"type":"string"}}/ - ); -}); diff --git a/packages/build/src/test/type-expressions/json-schema_test.ts b/packages/build/src/test/type-expressions/json-schema_test.ts deleted file mode 100644 index 5cf53632692..00000000000 --- a/packages/build/src/test/type-expressions/json-schema_test.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { jsonSchema } from "../../internal/type-system/json-schema.js"; -import { toJSONSchema } from "../../internal/type-system/type.js"; - -test("type and serialization", () => { - assert.deepEqual( - toJSONSchema( - // $ExpectType AdvancedBreadboardType - jsonSchema - ), - { - type: "object", - behavior: ["json-schema"], - properties: {}, - required: [], - additionalProperties: true, - } - ); -}); diff --git a/packages/build/src/test/type-expressions/object_test.ts b/packages/build/src/test/type-expressions/object_test.ts deleted file mode 100644 index 5e5e176dd87..00000000000 --- a/packages/build/src/test/type-expressions/object_test.ts +++ /dev/null @@ -1,198 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { anyOf, object, optional } from "@breadboard-ai/build"; -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { - toJSONSchema, - type ConvertBreadboardType, -} from "../../internal/type-system/type.js"; - -/* eslint-disable @typescript-eslint/no-unused-vars */ - -test("no arguments", () => { - // @ts-expect-error no arguments - assert.throws(() => object()); -}); - -test("empty object", () => { - const obj1 = object({}); - // $ExpectType object & JsonSerializable - type t1 = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(obj1), { - type: "object", - properties: {}, - required: [], - additionalProperties: false, - }); -}); - -test("object with string and number properties", () => { - const obj2 = object({ foo: "string", bar: "number" }); - // $ExpectType { foo: string; bar: number; } - type t2 = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(obj2), { - type: "object", - properties: { - foo: { - type: "string", - }, - bar: { - type: "number", - }, - }, - required: ["foo", "bar"], - additionalProperties: false, - }); -}); - -test("object with nested object", () => { - const obj3 = object({ foo: object({ bar: "string" }) }); - // $ExpectType { foo: { bar: string; }; } - type t3 = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(obj3), { - type: "object", - properties: { - foo: { - type: "object", - properties: { - bar: { - type: "string", - }, - }, - required: ["bar"], - additionalProperties: false, - }, - }, - required: ["foo"], - additionalProperties: false, - }); -}); - -test("object with anyOf type", () => { - const obj4 = object({ foo: anyOf("string", "number") }); - // $ExpectType { foo: string | number; } - type t4 = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(obj4), { - type: "object", - properties: { - foo: { type: ["string", "number"] }, - }, - required: ["foo"], - additionalProperties: false, - }); -}); - -test("object with anyOf type including object", () => { - const obj5 = object({ foo: anyOf("string", object({ bar: "string" })) }); - // $ExpectType { foo: string | { bar: string; }; } - type t5 = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(obj5), { - type: "object", - properties: { - foo: { - anyOf: [ - { type: "string" }, - { - type: "object", - properties: { bar: { type: "string" } }, - required: ["bar"], - additionalProperties: false, - }, - ], - }, - }, - required: ["foo"], - additionalProperties: false, - }); -}); - -test("object with unknown property", () => { - const obj = object({ foo: "unknown" }); - // $ExpectType { foo: JsonSerializable; } - type objType = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(obj), { - type: "object", - properties: { - foo: { - type: ["array", "boolean", "null", "number", "object", "string"], - }, - }, - required: ["foo"], - additionalProperties: false, - }); -}); - -test("object no known properties", () => { - const obj = object({}); - // $ExpectType object & JsonSerializable - type objType = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(obj), { - type: "object", - properties: {}, - required: [], - additionalProperties: false, - }); -}); - -test("empty object with additional string properties", () => { - const obj = object({}, "string"); - // $ExpectType { [x: string]: string; } - type objType = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(obj), { - type: "object", - properties: {}, - required: [], - additionalProperties: { type: "string" }, - }); -}); - -test("non-empty object with additional string|number properties", () => { - const obj = object({ foo: "string" }, anyOf("string", "number")); - // $ExpectType { [x: string]: string | number; foo: string; } - type objType = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(obj), { - type: "object", - properties: { - foo: { - type: "string", - }, - }, - required: ["foo"], - additionalProperties: { type: ["string", "number"] }, - }); -}); - -test("empty object with additional unknown properties", () => { - const obj = object({}, "unknown"); - // $ExpectType { [x: string]: JsonSerializable; } - type objType = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(obj), { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - }); -}); - -test("object with optional property", () => { - const obj = object({ - req: "number", - opt: optional("number"), - }); - // $ExpectType { req: number; opt?: number | undefined; } - type objType = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(obj), { - type: "object", - properties: { - opt: { type: "number" }, - req: { type: "number" }, - }, - required: ["req"], - additionalProperties: false, - }); -}); diff --git a/packages/build/src/test/type-expressions/string_test.ts b/packages/build/src/test/type-expressions/string_test.ts deleted file mode 100644 index af38780fa42..00000000000 --- a/packages/build/src/test/type-expressions/string_test.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { string } from "../../internal/type-system/string.js"; -import { - toJSONSchema, - type ConvertBreadboardType, -} from "../../internal/type-system/type.js"; - -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -test("no options", () => { - const t = string({}); - // $ExpectType string - type T = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(t), { - type: "string", - }); -}); - -test("1 option", () => { - const t = string({ format: "email" }); - // $ExpectType string - type T = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(t), { - type: "string", - format: "email", - }); -}); - -test("all options", () => { - const t = string({ - format: "uri", - pattern: "^.*$", - minLength: 2, - maxLength: 42, - }); - // $ExpectType string - type T = ConvertBreadboardType; - assert.deepEqual(toJSONSchema(t), { - type: "string", - format: "uri", - pattern: "^.*$", - minLength: 2, - maxLength: 42, - }); -}); - -test("error: unknown option", () => { - string({ - format: "uri", - // @ts-expect-error - potato: true, - }); -}); diff --git a/packages/build/src/test/type-expressions/unsafetype_test.ts b/packages/build/src/test/type-expressions/unsafetype_test.ts deleted file mode 100644 index 1978ce89ecb..00000000000 --- a/packages/build/src/test/type-expressions/unsafetype_test.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { unsafeType } from "@breadboard-ai/build"; -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { - toJSONSchema, - type BreadboardType, -} from "../../internal/type-system/type.js"; - -test("unsafeType", () => { - // @ts-expect-error no JSON schema - unsafeType(); - // @ts-expect-error invalid JSON schema - unsafeType(undefined); - // @ts-expect-error invalid JSON schema - unsafeType("string"); - - // $ExpectType AdvancedBreadboardType - const str = unsafeType({ type: "string" }) satisfies BreadboardType; - assert.deepEqual(toJSONSchema(str), { - type: "string", - }); - - // $ExpectType AdvancedBreadboardType - const strOrNum = unsafeType({ - anyOf: [{ type: "string" }, { type: "number" }], - }) satisfies BreadboardType; - assert.deepEqual(toJSONSchema(strOrNum), { - anyOf: [{ type: "string" }, { type: "number" }], - }); -}); diff --git a/packages/build/tsconfig.json b/packages/build/tsconfig.json deleted file mode 100644 index 4c0109444dd..00000000000 --- a/packages/build/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/.tsbuildinfo", - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "types": ["node"], - "lib": ["ES2022", "DOM"], - "incremental": true, - "declaration": true, - "sourceMap": true, - "inlineSources": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "noImplicitOverride": true, - "noUncheckedIndexedAccess": true, - "verbatimModuleSyntax": true, - "useUnknownInCatchVariables": true - }, - "include": ["src/**/*.ts"], - "exclude": [] -} diff --git a/packages/connection-server/.eslintrc b/packages/connection-server/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/connection-server/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/connection-server/.gcloudignore b/packages/connection-server/.gcloudignore deleted file mode 100644 index aea9870163d..00000000000 --- a/packages/connection-server/.gcloudignore +++ /dev/null @@ -1,22 +0,0 @@ -# This file specifies files that are *not* uploaded to Google Cloud -# using gcloud. It follows the same syntax as .gitignore, with the addition of -# "#!include" directives (which insert the entries of the given .gitignore-style -# file at that point). -# -# For more information, run: -# $ gcloud topic gcloudignore - -.eslintrc -.gcloudignore -.git -.gitignore -.npmignore -.wireit/ -app.\*.yaml -CHANGELOG.md -dist/.tsbuildinfo -dist/**/\*.d.ts -dist/**/\*.js.map -docs/ -node_modules/ -README.md diff --git a/packages/connection-server/.gitignore b/packages/connection-server/.gitignore deleted file mode 100644 index 0f1898183c2..00000000000 --- a/packages/connection-server/.gitignore +++ /dev/null @@ -1 +0,0 @@ -secrets/ \ No newline at end of file diff --git a/packages/connection-server/.npmignore b/packages/connection-server/.npmignore deleted file mode 100644 index 0f1898183c2..00000000000 --- a/packages/connection-server/.npmignore +++ /dev/null @@ -1 +0,0 @@ -secrets/ \ No newline at end of file diff --git a/packages/connection-server/CHANGELOG.md b/packages/connection-server/CHANGELOG.md deleted file mode 100644 index 0f66182bc79..00000000000 --- a/packages/connection-server/CHANGELOG.md +++ /dev/null @@ -1,35 +0,0 @@ -# @breadboard-ai/connection-server - -## 0.3.2 - -### Patch Changes - -- 90f1662: Teach App View about OAuth connection secrets. - -## 0.3.1 - -### Patch Changes - -- 84d56e0: Connection server now uses a single service config - -## 0.3.0 - -### Minor Changes - -- 98491df: The format of the secrets config file has changed (see README), and only one - file will now be read at a time -- the one defined in the `CONNECTIONS_FILE` - environment variable. - -### Patch Changes - -- 960922e: Store the OAuth client ID locally, in addition to the token details. Useful for APIs that require the client ID to be provided. - -## 0.2.0 - -### Minor Changes - -- 4ba1243: Migrate breadboard-ui to visual-editor - -### Patch Changes - -- ec2e0b1: Suggest a kill/lsof command when the port is in use diff --git a/packages/connection-server/README.md b/packages/connection-server/README.md deleted file mode 100644 index 8150ea5795a..00000000000 --- a/packages/connection-server/README.md +++ /dev/null @@ -1,141 +0,0 @@ -# Breadboard Connection Server - -A stateless service for coordinating authenticated connections between -Breadboard end-user clients and third-party apps/services using OAuth. - -## Contents - -- [Background](#background) -- [APIs](#apis) - - [GET list/](#get-list) - - [GET grant/](#get-grant) - - [GET refresh/](#get-refresh) -- [Configuring Connections](#configuring-connections) - - [Configuring Google Cloud Connections](#configuring-google-cloud-connections) -- [Local development](#local-development) -- [Production deployment](#production-deployment) - -## Background - -This README assumes knowledge of terms and concepts from [RFC 6749: The OAuth -2.0 Authorization Framework ](https://datatracker.ietf.org/doc/html/rfc6749), -especially: - -- [_authorization endpoint_](https://datatracker.ietf.org/doc/html/rfc6749#section-3.1) -- [_authorization code_](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.1) -- [_access token_](https://datatracker.ietf.org/doc/html/rfc6749#section-1.4) -- [_access token scope_](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3) -- [_refresh token_](https://datatracker.ietf.org/doc/html/rfc6749#section-1.5) - -Note the term _connection_ is not a standard OAuth term. We adopt this term to -refer to the high level process of an end-user "connecting" their client to a -third-party app/service. - -## APIs - -### `GET list/` - -List the available connections. - -Returns a list of all possible third-party apps/services that the end-user could -connect their Breadboard client to. See [Configuration Connections](#configuring-connections) for where this list comes from. - -Each connection includes an ID (allowing us to distinguish between the various -available connections), a display name and description, and a third-party -[authorization -endpoint](https://datatracker.ietf.org/doc/html/rfc6749#section-3.1) URL. - - - -### `GET grant/` - -Perform first-time authorization for a connection. - -Takes a connection ID and a temporary [authorization -code](https://datatracker.ietf.org/doc/html/rfc6749#section-1.3.1) (generated by -the third-party authorization endpoint and returned to the end-user via a -redirect). - -Returns an [access -token](https://datatracker.ietf.org/doc/html/rfc6749#section-1.4) which can be -used to access third-party resources, an expiry duration for that access token, -and a long-term [refresh -token](https://datatracker.ietf.org/doc/html/rfc6749#section-1.5) which can be -used to automatically acquire new access tokens without user interaction. - -### `GET refresh/` - -Get a new authorization token for when an earlier one has expired. - -Takes a connection ID and a refresh token. Returns a new access token and expiry -duration. - -## Configuring Connections - -> [!NOTE] -> In the future, connections will also be configurable via the Google Cloud -> [Secret Manager](https://cloud.google.com/secret-manager/docs). - -Connections are configured by placing a JSON file in this package's `secrets/` -folder, and setting the `CONNECTIONS_FILE` environment variable to its path. The -format of the JSON file follows this example: - -```json -{ - "connections": [ - { - "id": "cool-service", - "title": "Cool Service", - "description": "A cool service for doing cool stuff", - "oauth": { - "client_id": "an_oauth_client_id", - "client_secret": "the_secret_for_this_oauth_client", - "scopes": ["an_oauth_scope"], - "auth_uri": "https://example.com/auth", - "token_uri": "https://example.com/token" - }, - "icon": "data:image/png;base64,some_base64_bytes_of_a_png" - } - ] -} -``` - -> [!IMPORTANT] -> Connection configuration files should never be checked into GitHub or any -> other insecure location. -> -> This is because the `client_secret` field is highly sensitive. It allows any -> party to impersonate the application it belongs to and intercept user access -> tokens. The Breadboard Connection Server never reveals this secret over its -> APIs, and protecting these secrets is the primary reason this server exists. - -### Configuring Google Cloud Connections - -To configure a connection for a Google Cloud project: - -1. Follow the documentation at [Google Identity > OpenID - Connect](https://developers.google.com/identity/openid-connect/openid-connect) - to create and configure an OAuth 2.0 client. - -2. Download the OAuth 2.0 client's JSON configuration with the button shown - here: - - Screenshot of the "Client secrets" section of the Google Cloud OAuth 2.0 Client detail page with the "Download JSON" button highlighted - -3. Copy the the `client_id`, `client_secret`, `auth_uri`, and `token_uri` fields from this file - into the `CONNECTIONS_FILE` you have chosen (see above for example). - -## Local development - -```sh -cd breadboard/packages/connection-server -npm run dev -``` - -This will start the server on `localhost:5555`. Set the `HOST` and/or `PORT` -environment variables to customize the address. The server will automatically -restart if its implementation or connection configuration files are modified. diff --git a/packages/connection-server/app.yaml b/packages/connection-server/app.yaml deleted file mode 100644 index f04b6fafc38..00000000000 --- a/packages/connection-server/app.yaml +++ /dev/null @@ -1,15 +0,0 @@ -service: connections - -runtime: nodejs22 - -instance_class: F1 - -handlers: - - url: /.* - secure: always - redirect_http_response_code: 301 - script: auto - -env_variables: - CONNECTIONS_FILE: "secrets/secrets.json" - ALLOWED_ORIGINS: "" diff --git a/packages/connection-server/docs/gcp-client-secrets.png b/packages/connection-server/docs/gcp-client-secrets.png deleted file mode 100644 index 4daf14a7156..00000000000 Binary files a/packages/connection-server/docs/gcp-client-secrets.png and /dev/null differ diff --git a/packages/connection-server/package.json b/packages/connection-server/package.json deleted file mode 100644 index d68b8173428..00000000000 --- a/packages/connection-server/package.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "name": "@breadboard-ai/connection-server", - "private": true, - "version": "0.3.2", - "description": "Breadboard Connection Server", - "license": "Apache-2.0", - "author": "Google Labs Team", - "repository": { - "directory": "packages/connection-server", - "type": "git", - "url": "https://github.com/breadboard-ai/breadboard.git" - }, - "homepage": "https://github.com/breadboard-ai/breadboard#readme", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "files": [ - "dist/" - ], - "main": "./dist/index.js", - "exports": "./dist/index.js", - "types": "dist/index.d.ts", - "type": "module", - "scripts": { - "start": "node dist/index.js", - "dev": "npm run dev:nowatch --watch", - "dev:nowatch": "wireit", - "build": "wireit", - "build:tsc": "wireit", - "test": "echo \"no tests yet\"", - "lint": "wireit", - "prepack": "npm run build" - }, - "wireit": { - "dev:nowatch": { - "command": "[ -f ./secrets/local.json ] && export CONNECTIONS_FILE=./secrets/local.json; node --enable-source-maps dist/index.js", - "service": true, - "env": { - "ALLOWED_ORIGINS": "http://localhost:5173 http://localhost:3000" - }, - "dependencies": [ - "build" - ], - "files": [ - "secrets/" - ] - }, - "build": { - "dependencies": [ - "build:tsc" - ] - }, - "build:tsc": { - "command": "tsc --pretty", - "files": [ - "src/", - "tsconfig.json", - "package.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "lint": { - "command": "eslint src/ --ext .ts", - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - } - }, - "devDependencies": { - "@types/node": "^22.0.0", - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" - } -} diff --git a/packages/connection-server/src/api/grant.ts b/packages/connection-server/src/api/grant.ts deleted file mode 100644 index 06510c5d254..00000000000 --- a/packages/connection-server/src/api/grant.ts +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { IncomingMessage, ServerResponse } from "node:http"; -import type { ServerConfig } from "../config.js"; -import { badRequestJson, internalServerError, okJson } from "../responses.js"; - -interface GrantRequest { - connection_id: string; - code: string; - redirect_path: string; -} - -// IMPORTANT: Keep in sync with -// breadboard/packages/visual-editor/src/elements/connection/connection-common.ts -type GrantResponse = - | { error: string } - | { - error?: undefined; - access_token: string; - expires_in: number; - refresh_token: string; - }; - -/** - * API which performs first-time authorization for a connection. - */ -export async function grant( - req: IncomingMessage, - res: ServerResponse, - config: ServerConfig -): Promise { - const params = Object.fromEntries( - new URL(req.url ?? "", "http://example.com").searchParams.entries() - ) as object as GrantRequest; - if (!params.connection_id) { - return badRequestJson(res, { error: "missing connection_id" }); - } - if (!params.code) { - return badRequestJson(res, { error: "missing code" }); - } - - const connectionConfig = config.connections.get(params.connection_id); - if (!connectionConfig) { - return badRequestJson(res, { - error: `unknown connection ID "${params.connection_id}"`, - }); - } - - const tokenUrl = new URL(connectionConfig.oauth.token_uri); - tokenUrl.searchParams.set("grant_type", "authorization_code"); - tokenUrl.searchParams.set("code", params.code); - tokenUrl.searchParams.set( - "redirect_uri", - new URL(params.redirect_path, req.headers.origin).href - ); - tokenUrl.searchParams.set("client_id", connectionConfig.oauth.client_id); - tokenUrl.searchParams.set( - "client_secret", - connectionConfig.oauth.client_secret - ); - - const httpRes = await fetch(tokenUrl, { - method: "POST", - headers: { Accept: "application/json" }, - }); - let tokenResponse: TokenEndpointGrantResponse; - try { - tokenResponse = (await httpRes.json()) as TokenEndpointGrantResponse; - } catch (e) { - console.error( - `Could not read JSON response from grant token endpoint (status ${httpRes.status}): ${e}` - ); - return internalServerError( - res, - `Could not read JSON response from grant token endpoint (status ${httpRes.status})` - ); - } - - if ( - httpRes.status === 200 && - tokenResponse.error === undefined && - tokenResponse.access_token && - tokenResponse.refresh_token && - tokenResponse.expires_in >= 0 - ) { - return okJson(res, { - access_token: tokenResponse.access_token, - expires_in: tokenResponse.expires_in, - refresh_token: tokenResponse.refresh_token, - } satisfies GrantResponse); - } - - if (httpRes.status === 400) { - if (tokenResponse.error === "invalid_grant") { - // The token is expired. - return badRequestJson(res, { - error: "invalid_grant", - } satisfies GrantResponse); - } else if (tokenResponse.error === "redirect_uri_mismatch") { - // Our redirect URL is misconfigured somehow. - return badRequestJson(res, { - error: "redirect_uri_mismatch", - } satisfies GrantResponse); - } - } - - console.error( - `Unexpected HTTP ${httpRes.status} status from grant token endpoint ${tokenUrl}: -${JSON.stringify(tokenResponse, null, 2)}` - ); - return internalServerError( - res, - `Unexpected HTTP ${httpRes.status} status from grant token endpoint.` - ); -} - -type TokenEndpointGrantResponse = - | { - access_token: string; - refresh_token?: string; - expires_in: number; - error?: undefined; - } - | { - error: string; - }; diff --git a/packages/connection-server/src/api/list.ts b/packages/connection-server/src/api/list.ts deleted file mode 100644 index bfb6cabd547..00000000000 --- a/packages/connection-server/src/api/list.ts +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { IncomingMessage, ServerResponse } from "node:http"; -import type { ConnectionConfig, ServerConfig } from "../config.js"; -import { okJson } from "../responses.js"; - -// IMPORTANT: Keep in sync with -// breadboard/packages/visual-editor/src/elements/connection/connection-server.ts -interface ListConnectionsResponse { - connections: Connection[]; -} - -interface Connection { - id: string; - clientId: string; - authUrl: string; - title: string; - description?: string; - icon?: string; -} - -/** - * API which lists the available connections. - * - * Takes no parameters. Returns an array of servers. - */ -export async function list( - _req: IncomingMessage, - res: ServerResponse, - config: ServerConfig -): Promise { - const response: ListConnectionsResponse = { - connections: [...config.connections.values()] - .map((config) => { - const connection: Connection = { - id: config.id, - clientId: config.oauth.client_id, - authUrl: makeAuthorizationEndpointUrl(config), - title: config.title ?? config.id, - }; - if (config.description) { - connection.description = config.description; - } - if (config.icon) { - connection.icon = config.icon; - } - return connection; - }) - .sort(({ id: idA }, { id: idB }) => idA.localeCompare(idB)), - }; - return okJson(res, response); -} - -function makeAuthorizationEndpointUrl(config: ConnectionConfig): string { - const url = new URL(config.oauth.auth_uri); - const params = url.searchParams; - params.set("client_id", config.oauth.client_id); - params.set("scope", config.oauth.scopes.join(" ")); - params.set("response_type", "code"); - params.set("access_type", "offline"); - // Force re-consent every time, because we always want a refresh token. - params.set("prompt", "consent"); - return url.href; -} diff --git a/packages/connection-server/src/api/refresh.ts b/packages/connection-server/src/api/refresh.ts deleted file mode 100644 index 044da2b0f38..00000000000 --- a/packages/connection-server/src/api/refresh.ts +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { IncomingMessage, ServerResponse } from "node:http"; -import type { ServerConfig } from "../config.js"; -import { badRequestJson, internalServerError, okJson } from "../responses.js"; - -// IMPORTANT: Keep in sync with -// breadboard/packages/visual-editor/src/elements/connection/connection-input.ts -interface RefreshRequest { - connection_id: string; - refresh_token: string; -} - -type RefreshResponse = - | { error: string } - | { - error?: string; - access_token: string; - expires_in: number; - }; - -/** - * API which gets a new authorization token for when an earlier one has expired. - */ -export async function refresh( - req: IncomingMessage, - res: ServerResponse, - config: ServerConfig -): Promise { - const params = Object.fromEntries( - new URL(req.url ?? "", "http://example.com").searchParams.entries() - ) as object as RefreshRequest; - if (!params.connection_id) { - return badRequestJson(res, { error: "missing connection_id" }); - } - if (!params.refresh_token) { - return badRequestJson(res, { error: "missing refresh_token" }); - } - - const connectionConfig = config.connections.get(params.connection_id); - if (!connectionConfig) { - return badRequestJson(res, { - error: `unknown connection ID "${params.connection_id}"`, - }); - } - - const tokenUrl = new URL(connectionConfig.oauth.token_uri); - tokenUrl.searchParams.set("grant_type", "refresh_token"); - tokenUrl.searchParams.set("refresh_token", params.refresh_token); - tokenUrl.searchParams.set("client_id", connectionConfig.oauth.client_id); - tokenUrl.searchParams.set( - "client_secret", - connectionConfig.oauth.client_secret - ); - - const httpRes = await fetch(tokenUrl, { - method: "POST", - headers: { Accept: "application/json" }, - }); - let tokenResponse: TokenEndpointRefreshResponse; - try { - tokenResponse = (await httpRes.json()) as TokenEndpointRefreshResponse; - } catch (e) { - console.error( - `Could not read JSON response from refresh token endpoint (status ${httpRes.status}): ${e}` - ); - return internalServerError( - res, - `Could not read JSON response from refresh token endpoint (status ${httpRes.status})` - ); - } - - if ( - httpRes.status === 200 && - tokenResponse.error === undefined && - tokenResponse.access_token && - tokenResponse.expires_in >= 0 - ) { - return okJson(res, { - access_token: tokenResponse.access_token, - expires_in: tokenResponse.expires_in, - } satisfies RefreshResponse); - } - - console.error( - `Unexpected HTTP ${httpRes.status} status from refresh token endpoint endpoint ${tokenUrl}: -${JSON.stringify(tokenResponse, null, 2)}` - ); - return internalServerError( - res, - `Unexpected HTTP ${httpRes.status} status from refresh token endpoint endpoint.` - ); -} - -type TokenEndpointRefreshResponse = - | { - access_token: string; - expires_in: number; - error?: undefined; - } - | { - error: string; - }; diff --git a/packages/connection-server/src/config.ts b/packages/connection-server/src/config.ts deleted file mode 100644 index 36853602d24..00000000000 --- a/packages/connection-server/src/config.ts +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { readdir, readFile } from "node:fs/promises"; -import { join } from "node:path"; - -export interface ServerConfig { - connections: Map; - allowedOrigins: Set; -} - -export interface ConnectionsConfigFile { - connections: ConnectionConfig[]; -} - -export interface ConnectionConfig { - id: string; - title?: string; - description?: string; - icon?: string; - oauth: { - client_id: string; - client_secret: string; - auth_uri: string; - token_uri: string; - scopes: string[]; - }; -} - -export async function loadConnections( - configFilePath: string -): Promise> { - const config = JSON.parse( - await readFile(configFilePath, "utf8") - ) as ConnectionsConfigFile; - const connections = new Map(); - for (const connection of config.connections) { - if (connections.has(connection.id)) { - console.warn( - `Connection id ${connection.id} is configured more than once.` - ); - } else { - connections.set(connection.id, connection); - } - } - return connections; -} diff --git a/packages/connection-server/src/cors.ts b/packages/connection-server/src/cors.ts deleted file mode 100644 index 322c5125344..00000000000 --- a/packages/connection-server/src/cors.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - IncomingMessage, - OutgoingHttpHeaders, - ServerResponse, -} from "node:http"; - -const CORS_HEADERS: OutgoingHttpHeaders = { - "Access-Control-Allow-Methods": "GET", - "Access-Control-Allow-Headers": - "Content-Type, Access-Control-Allow-Headers, Authorization", - "Access-Control-Allow-Credentials": "true", - "Access-Control-Max-Age": 2592000, // 30 days -}; - -export const cors = ( - req: IncomingMessage, - res: ServerResponse, - allowedOrigins: Set -) => { - const headers = { ...CORS_HEADERS }; - const origin = req.headers.origin; - if (origin && allowedOrigins.has(origin)) { - headers["Access-Control-Allow-Origin"] = origin; - } - - if (req.method === "OPTIONS") { - res.writeHead(204, headers); - res.end(); - return null; - } - - const method = req.method || "GET"; - if (method === "GET") { - for (const [key, value] of Object.entries(headers)) { - if (value !== undefined) { - res.setHeader(key, value); - } - } - return true; - } - - res.writeHead(405, headers); - res.end(`${req.method} is not allowed for the request.`); - return false; -}; diff --git a/packages/connection-server/src/index.ts b/packages/connection-server/src/index.ts deleted file mode 100644 index 1ec390cf917..00000000000 --- a/packages/connection-server/src/index.ts +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createServer } from "node:http"; -import { env } from "node:process"; -import { loadConnections, type ServerConfig } from "./config.js"; -import { makeRouter } from "./router.js"; - -const configPath = process.env["CONNECTIONS_FILE"]; -const config: ServerConfig = { - connections: configPath ? await loadConnections(configPath) : new Map(), - allowedOrigins: new Set( - (process.env["ALLOWED_ORIGINS"] ?? "") - .split(/\s+/) - .filter((origin) => origin !== "") - ), -}; -if (config.connections.size === 0) { - console.log( - ` -┌─────────────────────────────────────────────────────────────────────────┐ -│ Breadboard Connection Server │ -├─────────────────────────────────────────────────────────────────────────┤ -│ No connection configurations were discovered, so no connections will be │ -│ available from this Breadboard Connection Server. │ -│ │ -│ See README.md#configuring-connections for more information. │ -└─────────────────────────────────────────────────────────────────────────┘ -` - ); -} -if (config.allowedOrigins.size === 0) { - console.log( - ` -┌─────────────────────────────────────────────────────────────────────────┐ -│ Breadboard Connection Server │ -├─────────────────────────────────────────────────────────────────────────┤ -│ No allowed origins were set. Place a space-delimited list of 1+ allowed │ -│ origins in the ALLOWED_ORIGINS environment variable and restart. │ -└─────────────────────────────────────────────────────────────────────────┘ -` - ); -} -const host = env.HOST || "localhost"; -const port = env.PORT ? Number(env.PORT) : 5555; -const server = createServer(makeRouter(config)); -server.on("error", (error) => { - console.error(error); - if ((error as { code?: string }).code === "EADDRINUSE") { - console.log( - ` -┌─────────────────────────────────────────────────────────────────────────┐ -│ Breadboard Connection Server │ -├─────────────────────────────────────────────────────────────────────────┤ -│ Port ${port} is in use by another process. Try this command to kill it: │ -│ │ -│ kill $(lsof -i tcp:${port} | tail -n 1 | head -n1 | cut -w -f2) │ -└─────────────────────────────────────────────────────────────────────────┘ -` - ); - } -}); - -server.listen(port, host, () => { - console.info( - ` -┌─────────────────────────────────────────────────────────────────────────┐ -│ Breadboard Connection Server │ -├─────────────────────────────────────────────────────────────────────────┘ -│ Listening on "http://${host}:${port}"... -└────────────────────────────────────────────────────────────────────────── -` - ); -}); diff --git a/packages/connection-server/src/responses.ts b/packages/connection-server/src/responses.ts deleted file mode 100644 index f90b08c0a76..00000000000 --- a/packages/connection-server/src/responses.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { ServerResponse } from "node:http"; - -export const internalServerError = ( - res: ServerResponse, - message: string -): void => { - res.writeHead(500, message); - res.end(message); -}; - -export const notFound = (res: ServerResponse, message: string): void => { - res.writeHead(404); - res.end(message); -}; - -export const okJson = (res: ServerResponse, data: unknown): void => { - res.writeHead(200, { "Content-Type": "application/json" }); - res.end(JSON.stringify(data, null, 2)); -}; - -export const badRequestJson = (res: ServerResponse, data: unknown): void => { - res.writeHead(400, { "Content-Type": "application/json" }); - res.end(JSON.stringify(data, null, 2)); -}; diff --git a/packages/connection-server/src/router.ts b/packages/connection-server/src/router.ts deleted file mode 100644 index 3bbd46c362f..00000000000 --- a/packages/connection-server/src/router.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { IncomingMessage, ServerResponse } from "node:http"; -import { grant } from "./api/grant.js"; -import { list } from "./api/list.js"; -import { refresh } from "./api/refresh.js"; -import type { ServerConfig } from "./config.js"; -import { cors } from "./cors.js"; -import { internalServerError, notFound } from "./responses.js"; - -export function makeRouter(config: ServerConfig) { - return async function router( - req: IncomingMessage, - res: ServerResponse - ): Promise { - if (!cors(req, res, config.allowedOrigins)) { - return; - } - try { - const path = new URL(req.url ?? "", "http://example.com").pathname; - switch (path) { - case "/list": { - return await list(req, res, config); - } - case "/grant": { - return await grant(req, res, config); - } - case "/refresh": { - return await refresh(req, res, config); - } - default: { - return notFound(res, `Page "${path}" does not exist`); - } - } - } catch (err) { - console.error( - err instanceof Error ? err.stack ?? err.message : String(err) - ); - return internalServerError(res, `Uncaught exception`); - } - }; -} diff --git a/packages/connection-server/tsconfig.json b/packages/connection-server/tsconfig.json deleted file mode 100644 index c53c59c2492..00000000000 --- a/packages/connection-server/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/.tsbuildinfo", - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "types": ["node"], - "lib": ["ES2022"], - "incremental": true, - "declaration": true, - "sourceMap": true, - "inlineSources": true, - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "noImplicitOverride": true, - "noUncheckedIndexedAccess": true, - "verbatimModuleSyntax": true, - "useUnknownInCatchVariables": true - }, - "include": ["src/**/*.ts"], - "exclude": [] -} diff --git a/packages/core-kit/.eslintrc b/packages/core-kit/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/core-kit/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/core-kit/.npmignore b/packages/core-kit/.npmignore deleted file mode 100644 index 7ddb2133685..00000000000 --- a/packages/core-kit/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -tsconfig.tsbuildinfo diff --git a/packages/core-kit/CHANGELOG.md b/packages/core-kit/CHANGELOG.md deleted file mode 100644 index f1baac126ae..00000000000 --- a/packages/core-kit/CHANGELOG.md +++ /dev/null @@ -1,624 +0,0 @@ -# Changelog - -## 0.15.0 - -### Minor Changes - -- 4dadf16: Introduce experimental storeData and retrieveData components in Core Kit. -- f61ccf3: Introduce URL-based component types. -- b673bfa: Migrate curry to build api -- 4423c35: Switch runJavascript worker to be a module worker. - -### Patch Changes - -- 54c8197: Make build API kit function async -- 88298d5: The result of calling code() now includes a test() method which can be used to directly invoke the function. Useful for testing so that you don't need to factor out a separate function. -- feeed7a: Allow map to take string boards, and export a coreKit object for build api -- 9783ba8: Fix worker memory leak and throttle describers. -- 9c04caa: Convert reduce to build api -- Updated dependencies [49e2740] -- Updated dependencies [54c8197] -- Updated dependencies [703f17d] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [8f9fddf] -- Updated dependencies [2fa05f0] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [f71bcfb] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [3188607] -- Updated dependencies [9797718] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [8330f0c] -- Updated dependencies [a039d2e] -- Updated dependencies [1423647] -- Updated dependencies [9783ba8] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [91fe8bb] -- Updated dependencies [100fc95] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [5834c81] -- Updated dependencies [d7606d3] -- Updated dependencies [0ef793f] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] - - @breadboard-ai/build@0.10.0 - - @google-labs/breadboard@0.27.0 - -## 0.14.1 - -### Patch Changes - -- 85fb144: Support passing \* StarInputs to code helper -- Updated dependencies [bbcdd2d] -- Updated dependencies [9ed58cf] -- Updated dependencies [7f2ef33] -- Updated dependencies [7d46a63] -- Updated dependencies [bac2e35] -- Updated dependencies [ec2fedd] - - @breadboard-ai/build@0.9.1 - - @google-labs/breadboard@0.26.0 - -## 0.14.0 - -### Minor Changes - -- a4301e6: Introduce the ability to write custom describers. -- 7de241c: Remove `BoardRunner`. -- ee1f9ca: Throttle describe requests to once every 5 seconds. - -### Patch Changes - -- cc5f4b6: Updates for new board function API in build package -- Updated dependencies [cc5f4b6] -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [a940b87] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [374ea85] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [f93ec06] -- Updated dependencies [398bf4f] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @breadboard-ai/build@0.9.0 - - @google-labs/breadboard@0.25.0 - -## 0.13.0 - -### Minor Changes - -- 00cc2c5: Remove `lambda`, introduce standalone `invokeGraph` and `runGraph` functions, and other plumbing refactoring. -- 3a5ced1: Refactor `map` to run serially when `RunStateManager` is present. - -### Patch Changes - -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [1dc645a] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [c04cff0] -- Updated dependencies [d88c37b] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - - @breadboard-ai/build@0.8.1 - -## 0.12.0 - -### Minor Changes - -- 6d2939e: Remove the ability to bubble up inputs from `map` component. -- 7298a47: Add simplistic caching to `service` component. - -### Patch Changes - -- 5c5b665: Stop leaking blob URLs in runJavascript. -- a0852df: Update titles and help links in Core Kit. -- ea7e2a1: Mark `schema` as deprecated on `runJavascript`. -- 8edcbc0: Update Template and Core Kit to jive with docs. -- 9a2ffab: Unpin @breadboard-ai/build dependency from being overly constrained -- b99472b: Update titles in `curry` component. -- 4bfaec5: Improve documentation/metadata for unnest and cast nodes -- Updated dependencies [ad8aa22] -- Updated dependencies [1e1be2a] -- Updated dependencies [2b094a3] -- Updated dependencies [fa93c3f] -- Updated dependencies [f78ec0a] -- Updated dependencies [215bd15] -- Updated dependencies [2b9ef5b] -- Updated dependencies [a0852df] -- Updated dependencies [2312443] -- Updated dependencies [b76f9a1] -- Updated dependencies [6ffa89c] -- Updated dependencies [15ae381] - - @breadboard-ai/build@0.8.0 - - @google-labs/breadboard@0.23.0 - -## 0.11.0 - -### Minor Changes - -- 166f290: Introduce `service` node. - -### Patch Changes - -- f4d2416: Add cast node and helper to core-kit, for asserting some JSON schema as the type of some value. -- bc94299: The unnest node now uses the actual describe function of the connected node to discover the incoming schema, and sets the outgoing schema to match. -- 9d93cf8: Added inputSchema and outputSchema properties. The old "schema" property is now deprecated in favor of "outputSchema" (though will fall back to "schema"). -- 9d93cf8: Add extractTypeFromValue function. -- a9def5c: Fix bug in automatic output schema when using code helper. -- Updated dependencies [a925cf0] -- Updated dependencies [da43bb5] -- Updated dependencies [5cf08f1] -- Updated dependencies [ffbf163] -- Updated dependencies [8928fb7] -- Updated dependencies [9d93cf8] -- Updated dependencies [d6706f2] -- Updated dependencies [5447426] -- Updated dependencies [26e1099] -- Updated dependencies [7e1f01c] - - @google-labs/breadboard@0.22.0 - - @breadboard-ai/build@0.7.1 - -## 0.10.1 - -### Patch Changes - -- 29774aa: Update dependency package versions. - -## 0.10.0 - -### Minor Changes - -- c27c176: Actually commit the runJavascript change -- 4e66406: Automatically handle errors in `map`. -- 417323c: Teach Board Server to use Node Proxy Server -- 4db3ab7: Teach `runJavascript` to be kind fo esbuild. -- d9b76bd: Teach fetch to handle blob responses. -- 14853d5: Add Gemini Nano node. -- 3e10f0f: Introduce `DataCapability` and add support for multipart form data in `fetch`. -- c53ca01: Plumb `DataStore` throuh to `NodeHandlerContext`. -- 0e76614: Fetch will now treat any text/\* MIME type as text -- 2ace620: Teach `InspectableGraph.describe` to correctly propagate fixed/flexible bit. -- 26556b6: Teachs runJavaScript to accept a schema -- 5f09b1d: Teach runJavascript to report errors. -- 510e198: Convert map to new build API -- 9491266: Introduce `deflate` node. - -### Patch Changes - -- 85bbc00: Teach runJavascript to run in Service Workers. -- 5a0afe4: Add inflate node -- 6fdd89e: Add unnest node, for expanding an object value with N properties into a node with N output ports -- c82138d: Allow code nodes to return promises -- 0e54e55: Mark `$board` port as `config` on `invoke` node. -- b75a43e: Change `invoke.$board` input to `object` type. -- 6fdd89e: Mark "response" as the primary output of fetch -- 9b1513a: Make sure `structuredClone` is available when running JS in Node. -- Updated dependencies [5a55b7d] -- Updated dependencies [74ade20] -- Updated dependencies [59dd0f5] -- Updated dependencies [417323c] -- Updated dependencies [b3aa884] -- Updated dependencies [00825d5] -- Updated dependencies [3d7b4a7] -- Updated dependencies [7af14cf] -- Updated dependencies [fea8967] -- Updated dependencies [778f7aa] -- Updated dependencies [808f5e2] -- Updated dependencies [e0fdbc3] -- Updated dependencies [54b03b9] -- Updated dependencies [810d7fd] -- Updated dependencies [14853d5] -- Updated dependencies [8798514] -- Updated dependencies [eb64b9a] -- Updated dependencies [32a48a3] -- Updated dependencies [cd73b17] -- Updated dependencies [81d82fe] -- Updated dependencies [2a7531b] -- Updated dependencies [7c1b4cb] -- Updated dependencies [702cfe1] -- Updated dependencies [bebd96e] -- Updated dependencies [91cb723] -- Updated dependencies [3e10f0f] -- Updated dependencies [c53ca01] -- Updated dependencies [6ada218] -- Updated dependencies [4c681cb] -- Updated dependencies [fb2e584] -- Updated dependencies [9491266] -- Updated dependencies [2ace620] -- Updated dependencies [c5f8e4f] -- Updated dependencies [fcef799] -- Updated dependencies [37418d9] -- Updated dependencies [083f69c] -- Updated dependencies [5b03d96] -- Updated dependencies [f0d8d67] -- Updated dependencies [836389d] -- Updated dependencies [225c7cc] -- Updated dependencies [06c3f57] - - @google-labs/breadboard@0.21.0 - - @breadboard-ai/build@0.7.0 - -## 0.9.0 - -### Minor Changes - -- af54870: Convert passthrough to new API. The output schema of passthrough is now taken from the connected inputSchema instead of just using the values. This preserves more information about the ports that are being passed-through. - -### Patch Changes - -- 8774855: Allow code outputs to be optional -- 1b596d4: Add a `code` function which creates a `runJavascript` node in a type-safe way. -- 4957dc5: Handle the case in secrets describe where there are no input keys yet -- ee85b67: Add a `secret` function which creates and configures a `secrets` node for just - one secret, and returns the corresponding output port. A simpler way to get - secrets in the API. -- 1d29493: Export passthrough node definition -- f870bdd: Allow returning errors from code helper function -- Updated dependencies [8097177] -- Updated dependencies [29eda71] -- Updated dependencies [f60cb06] -- Updated dependencies [cec6d54] -- Updated dependencies [87eb8fe] -- Updated dependencies [f97a4d5] -- Updated dependencies [60a18c5] -- Updated dependencies [b0ed6f3] -- Updated dependencies [4957dc5] -- Updated dependencies [a209c51] -- Updated dependencies [3397974] -- Updated dependencies [7368fdd] -- Updated dependencies [c9c0e06] -- Updated dependencies [c1acf24] -- Updated dependencies [3920805] -- Updated dependencies [ab9a4ce] -- Updated dependencies [3b2bb4a] -- Updated dependencies [a35406c] -- Updated dependencies [31cf016] -- Updated dependencies [ab43276] -- Updated dependencies [477e6e6] -- Updated dependencies [cdcbcdb] -- Updated dependencies [791ec2a] -- Updated dependencies [c0293c9] -- Updated dependencies [b6f5644] -- Updated dependencies [43edef6] - - @google-labs/breadboard@0.20.0 - - @breadboard-ai/build@0.6.0 - -## 0.8.1 - -### Patch Changes - -- Updated dependencies [63eb779] - - @google-labs/breadboard@0.19.0 - - @breadboard-ai/build@0.5.1 - -## 0.8.0 - -### Minor Changes - -- fefd109: The fetch node is now implemented with @breadboard-ai/build. This should not affect any board behavior. -- 34d9c6d: fetch, secrets, and run-javascript are slightly more correct in their descriptions (object vs any JSON value) -- c117d4f: Port runJavascript node to @breadboard-ai/build - -### Patch Changes - -- 54baba8: Implement `AbortSignal` support. -- 416aed2: Introduce `metadata` for `NodeHandler` entries, teaching node types in Kits to describe themselves. -- f2eda0b: Fix lots of bugs around Tool Worker. -- 776f043: Export fetch, invoke, runJavascript, and secrets node definitions -- Updated dependencies [3f9507d] -- Updated dependencies [cef20ca] -- Updated dependencies [55a9647] -- Updated dependencies [1e86a87] -- Updated dependencies [3f9507d] -- Updated dependencies [1adb24c] -- Updated dependencies [1e86a87] -- Updated dependencies [fbf7a83] -- Updated dependencies [fefd109] -- Updated dependencies [c1dcb0a] -- Updated dependencies [54baba8] -- Updated dependencies [49c3aa1] -- Updated dependencies [cdc23bb] -- Updated dependencies [416aed2] -- Updated dependencies [1adb24c] -- Updated dependencies [a1fcaea] -- Updated dependencies [d9ac358] -- Updated dependencies [c3ed6a7] -- Updated dependencies [f1883d1] -- Updated dependencies [1adb24c] -- Updated dependencies [d8cb0c9] -- Updated dependencies [34d9c6d] -- Updated dependencies [e6e0168] -- Updated dependencies [3d48482] -- Updated dependencies [1adb24c] -- Updated dependencies [f2eda0b] -- Updated dependencies [3f9507d] -- Updated dependencies [626139b] -- Updated dependencies [1adb24c] -- Updated dependencies [3f9507d] -- Updated dependencies [bd44e29] -- Updated dependencies [c4ca6dc] -- Updated dependencies [1adb24c] -- Updated dependencies [cfbcdf2] -- Updated dependencies [1d9cb16] -- Updated dependencies [49da151] -- Updated dependencies [43da00a] -- Updated dependencies [3f9507d] -- Updated dependencies [dfd5ce2] -- Updated dependencies [cfc0f15] -- Updated dependencies [00ccb9d] -- Updated dependencies [08eabf4] -- Updated dependencies [c3587e1] -- Updated dependencies [99fcffe] -- Updated dependencies [1e86a87] -- Updated dependencies [3f9507d] -- Updated dependencies [d9ac358] - - @breadboard-ai/build@0.5.0 - - @google-labs/breadboard@0.18.0 - -## 0.7.0 - -### Minor Changes - -- 0831735: Introduce `curry` node. -- d60f38b: Deprecate `path` on `core.invoke`. - -### Patch Changes - -- 5602f1e: Remove the warning when encountering unknown function format. -- Updated dependencies [c3cb25f] -- Updated dependencies [ae79e4a] -- Updated dependencies [72c5c6b] -- Updated dependencies [dd810dd] -- Updated dependencies [c5ba396] -- Updated dependencies [7bafa40] -- Updated dependencies [2932f4b] -- Updated dependencies [51159c4] -- Updated dependencies [6f9ba52] - - @google-labs/breadboard@0.17.0 - -## 0.6.0 - -### Minor Changes - -- 9d19852: Teach `map` and `reduce` to support embedded subgraphs. - -### Patch Changes - -- Updated dependencies [ad9c233] -- Updated dependencies [65d869b] -- Updated dependencies [417cdf5] -- Updated dependencies [cf0ee4f] -- Updated dependencies [43cbed7] -- Updated dependencies [ff6433c] -- Updated dependencies [5382365] -- Updated dependencies [0e7f106] -- Updated dependencies [9ea6ba0] -- Updated dependencies [ffd2a6c] - - @google-labs/breadboard@0.16.0 - -## 0.5.3 - -### Patch Changes - -- 182a546: Do not throw in `invoke` describer when board couldn't be loaded. -- Updated dependencies [76da09d] -- Updated dependencies [938015d] - - @google-labs/breadboard@0.15.0 - -## 0.5.2 - -### Patch Changes - -- Updated dependencies [e8d0737] - - @google-labs/breadboard@0.14.0 - -## 0.5.1 - -### Patch Changes - -- faf1e12: Teach invoke to be more accepting of uncertainty. -- Updated dependencies [faf1e12] -- Updated dependencies [51a38c0] -- Updated dependencies [d49b80e] -- Updated dependencies [9326bd7] -- Updated dependencies [fbad949] - - @google-labs/breadboard@0.13.0 - -## 0.5.0 - -### Minor Changes - -- 866fc36: Refactor `BoardLoader` to be a `GraphLoader` implementation. - -### Patch Changes - -- f73c637: Teach the `secrets` node to be more resilient with inputs. -- 99446b8: Various quality improvements to schemas and Graph Inspector API. -- 49c25aa: Add describers for a few nodes. -- ad5c1be: Introduce Tool Worker node in Agent Kit. -- bac9bb1: Bring loader machinery closer to cacheable load state. -- Updated dependencies [99446b8] -- Updated dependencies [866fc36] -- Updated dependencies [a8bab08] -- Updated dependencies [decfa29] -- Updated dependencies [f005b3b] -- Updated dependencies [dcfdc37] -- Updated dependencies [d971aad] -- Updated dependencies [048e8ec] -- Updated dependencies [dc35601] -- Updated dependencies [9cda2ff] -- Updated dependencies [60bd63c] -- Updated dependencies [764ccda] -- Updated dependencies [04d5420] -- Updated dependencies [56b90a4] -- Updated dependencies [1b48826] -- Updated dependencies [e648f64] -- Updated dependencies [ad5c1be] -- Updated dependencies [4a4a1f6] -- Updated dependencies [bac9bb1] -- Updated dependencies [3e8cfcf] -- Updated dependencies [986af39] -- Updated dependencies [3c497b0] -- Updated dependencies [eabd97b] -- Updated dependencies [2008f69] -- Updated dependencies [c0f785a] -- Updated dependencies [a8fc3f3] -- Updated dependencies [32cfbaf] -- Updated dependencies [8dc4e00] -- Updated dependencies [6438930] -- Updated dependencies [dd2cce6] -- Updated dependencies [cac4f4f] -- Updated dependencies [b1fc53b] -- Updated dependencies [ef05634] -- Updated dependencies [c208cfc] - - @google-labs/breadboard@0.12.0 - -## 0.4.0 - -### Minor Changes - -- 26367fe: Fixing typo in describe that would mean passthrough and reflect would not tell the system of their inputs - -### Patch Changes - -- Updated dependencies [07e66bf] - - @google-labs/breadboard@0.11.2 - -## 0.3.1 - -### Patch Changes - -- 3ed66b9: Add a resolve node to core-kit which resolves relative URLs to absolute URLs. -- Updated dependencies [05136f8] -- Updated dependencies [ef305d1] -- Updated dependencies [aea9178] -- Updated dependencies [20a0e5c] - - @google-labs/breadboard@0.11.1 - -## 0.3.0 - -### Minor Changes - -- 4c5b853: Implement output bubbling. -- 3f3f090: Teach `jsonata` and `invoke` nodes to better describe themselves. - -### Patch Changes - -- a9daeda: Introduce Repeater node in Agent Kit. -- 4920d90: Taught `core.invoke` to describe its own subgraphs. -- Updated dependencies [c19513e] -- Updated dependencies [2237a4c] -- Updated dependencies [bd68ebd] -- Updated dependencies [9a76a87] -- Updated dependencies [ea652f3] -- Updated dependencies [56954c1] -- Updated dependencies [0085ee2] -- Updated dependencies [0ef9ec5] -- Updated dependencies [ee00249] -- Updated dependencies [c13513f] -- Updated dependencies [56ccae5] -- Updated dependencies [4920d90] -- Updated dependencies [10a8129] -- Updated dependencies [c804ccc] -- Updated dependencies [5a65297] -- Updated dependencies [53406ad] -- Updated dependencies [4c5b853] -- Updated dependencies [3f3f090] -- Updated dependencies [d7a7903] -- Updated dependencies [4401a98] -- Updated dependencies [f6e9b2c] - - @google-labs/breadboard@0.11.0 - -## 0.2.2 - -### Patch Changes - -- 3e56a4f: Added a few TSDoc comments to kits for Intellisense. -- Updated dependencies [fb1c768] - - @google-labs/breadboard@0.10.1 - -## 0.2.1 - -### Patch Changes - -- Updated dependencies [9bcd607] -- Updated dependencies [f6a7f43] - - @google-labs/breadboard@0.10.0 - -## 0.2.0 - -### Minor Changes - -- c89b67a: Introduce the `reduce` node. - -### Patch Changes - -- 931a95b: Introduce richer error reporting to the harness. -- Updated dependencies [8eccdad] -- Updated dependencies [6e8c08d] -- Updated dependencies [780909c] -- Updated dependencies [bba68fd] -- Updated dependencies [b557794] -- Updated dependencies [a9206fc] -- Updated dependencies [931a95b] - - @google-labs/breadboard@0.9.0 - -## 0.1.3 - -### Patch Changes - -- Updated dependencies [af00e58] - - @google-labs/breadboard@0.8.0 - -## [0.1.2] - 2024-01-14 - -- Update build. Oops. - -## [0.1.1] - 2024-01-14 - -- Update dependencies. - -## [0.1.0] - 2023-12-06 - -- Bump dependencies. -- The `append` node now supports flattening and properly appends to arrays. - -## [0.0.1] - 2023-11-08 - -- First release. Contains the following nodes: - - Moved from Breadboard: `passthrough`, `reflect`, `slot`, `include`, `import`, and `invoke` - - Graduated from Node Nursery: `batch`, `map` diff --git a/packages/core-kit/README.md b/packages/core-kit/README.md deleted file mode 100644 index 68b1e362180..00000000000 --- a/packages/core-kit/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Breadboard Core Kit - -![Stability](https://img.shields.io/badge/stability-wip-green) - -A Kit containing components that enable composition and reuse of boards. - -See [docs](https://breadboard-ai.github.io/breadboard/docs/kits/core/) for the component reference. diff --git a/packages/core-kit/package.json b/packages/core-kit/package.json deleted file mode 100644 index 3c823743795..00000000000 --- a/packages/core-kit/package.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "name": "@google-labs/core-kit", - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "version": "0.15.0", - "description": "A Breadboard Kit containing nodes that enable composition and reuse of boards.", - "main": "./dist/src/index.js", - "exports": "./dist/src/index.js", - "types": "dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "test": "wireit", - "lint": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "../breadboard:build", - "../template-kit:build", - "../build:build", - "build:tsc" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "../breadboard:build:tsc", - "../template-kit:build:tsc", - "../build:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "test": { - "dependencies": [ - "test:ava", - "test:node" - ] - }, - "test:ava": { - "command": "ava", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - "tests/**/*.json", - "!tests/node/**/*.ts" - ], - "output": [] - }, - "test:node": { - "command": "node --test --enable-source-maps --test-reporter spec dist/tests/node/*.js", - "dependencies": [ - "build:tsc" - ], - "files": [ - "tests/node/*.ts", - "tests/boards/*.json" - ], - "output": [] - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - } - }, - "repository": { - "directory": "packages/core-kit", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src" - ], - "ava": { - "timeout": "30s", - "files": [ - "tests/**/*.ts", - "!tests/node/**/*.ts" - ], - "workerThreads": false, - "typescript": { - "rewritePaths": { - "./": "dist/" - }, - "compile": false - } - }, - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/core-kit#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/template-kit": "^0.3.10", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "typescript": "^5.6.2" - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@google-labs/breadboard": "^0.27.0" - } -} diff --git a/packages/core-kit/src/index.ts b/packages/core-kit/src/index.ts deleted file mode 100644 index 3d596d90b12..00000000000 --- a/packages/core-kit/src/index.ts +++ /dev/null @@ -1,408 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { KitBuilder } from "@google-labs/breadboard/kits"; - -import append from "./nodes/append.js"; -import batch from "./nodes/batch.js"; -import { castNode } from "./nodes/cast.js"; -import fetch from "./nodes/fetch.js"; -import importHandler from "./nodes/import.js"; -import include from "./nodes/include.js"; -import invoke from "./nodes/invoke.js"; -import map from "./nodes/map.js"; -import passthrough from "./nodes/passthrough.js"; -import reduce from "./nodes/reduce.js"; -import reflect from "./nodes/reflect.js"; -import resolve from "./nodes/resolve.js"; -import runJavascript from "./nodes/run-javascript.js"; -import secrets from "./nodes/secrets.js"; -import service from "./nodes/service.js"; -import slot from "./nodes/slot.js"; -import { unnestNode } from "./nodes/unnest.js"; - -export { cast, castNode } from "./nodes/cast.js"; -export { code } from "./nodes/code.js"; -export type { CodeNode } from "./nodes/code.js"; -export { default as fetch } from "./nodes/fetch.js"; -export { default as invoke } from "./nodes/invoke.js"; -export { map, default as mapNode } from "./nodes/map.js"; -export { default as passthrough } from "./nodes/passthrough.js"; -export { default as runJavascript } from "./nodes/run-javascript.js"; -export { secret, default as secrets } from "./nodes/secrets.js"; -export { unnest, unnestNode } from "./nodes/unnest.js"; -import { storeDataNode } from "./nodes/storeData.js"; -import { retrieveDataNode } from "./nodes/retrieveData.js"; - -const metadata = { - title: "Core Kit", - description: "A Breadboard kit that enables composition and reuse of boards", - version: "0.0.1", - url: "npm:@google-labs/core-kit", -}; - -const builder = new KitBuilder(metadata); - -export const Core = builder.build({ - /** - * Places an `import` node on the board. - * - * Use this node to import other boards into the current board. - * Outputs `board` as a BoardCapability, which can be passed to e.g. `invoke`. - * - * The config param expects either `path` or `graph` as a string or - * `GraphDescriptor', respectively. - * - * @param config - optional configuration for the node. - * @returns - a `Node` object that represents the placed node. - */ - import: importHandler, - - /** - * Places an `include` node on the board. - * - * Use this node to include other boards into the current board. - * - * The `include` node acts as a sort of instant board-to-node converter: just - * give it the URL of a serialized board, and it will pretend as if that whole - * board is just one node. - * - * See [`include` node - * reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/breadboard/docs/nodes.md#include) - * for more information. - * - * @param $ref - the URL of the board to include, or a graph or a - * BreadboardCapability returned by e.g. lambda. - * @param config - optional configuration for the node. - * @returns - a `Node` object that represents the placed node. - */ - include, - - /** - * Places an `invoke` node on the board. - * - * Use this node to invoke other boards into the current board. - * - * See [`include` node - * reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/breadboard/docs/nodes.md#include) - * for more information. - * - * Expects as input one of - * - `path`: A board to be loaded - * - `graph`: A graph (treated as JSON) - * - `board`: A {BreadboardCapability}, e.g. from lambda or import - * - * All other inputs are passed to the invoked board, - * and the output are the invoked board's outputs. - * - * @param config - optional configuration for the node. - * @returns - a `Node` object that represents the placed node. - */ - invoke, - - /** - * Places a `resolve` node on the board. - * - * Use this node to resolve relative URLs to absolute URLs. - * - * `resolve` has one special input: - * - `$base`: The base URL to use for resolution. If not provided, the URL of - * the current graph is used by default. - * - * All other inputs will be resolved to absolute URLs and returned on output - * ports with the same names as the corresponding input. - * - * @param config - optional configuration for the node. - * @returns - a `Node` object that represents the placed node. - */ - resolve, - - /** - * Places the `passthrough` node on the board. - * - * A `passthrough` node is a node that simply passes its inputs to - * its outputs. Every computing machine needs a no-op node, - * and Breadboard library is no exception. - * - * See [`passthrough` node reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/breadboard/docs/nodes.md#passthrough) for more information. - * - * @param config - optional configuration for the node. - * @returns - a `Node` object that represents the placed node. - */ - passthrough, - - /** - * Places a `reflect` node on the board. - * - * This node is used to reflect the board itself. It provides a JSON - * representation of the board as a `graph` output property. This can be - * used for studying the board's structure from inside the board. - * - * See [`reflect` node reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/breadboard/docs/nodes.md#reflect) for more information. - * - * @param config - optional configuration for the node. - * @returns - a `Node` object that represents the placed node. - */ - reflect, - - /** - * Places a `slot` node on the board. - * - * This node is used to provide a slot for another board to be placed into. - * - * This type of node is useful for situations where we wish to leave - * a place in the board where anyone could insert other boards. - * - * Programmers call it "dependency injection". - * - * See [`slot` node reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/breadboard/docs/nodes.md#slot) for more information. - * - * @param config - optional configuration for the node. - * @returns - a `Node` object that represents the placed node. - */ - slot, - - /** - * Use this node to accumulate local state, like context in a prompt. - * - * The node looks for property called `accumulator` in its input. All other - * properties are appended to this property, and returned as `accumulator` - * output property. - * - * The way the properties are appended depends on the type of the - * `accumulator` input property. - * - * If the `accumulator` property is "string-ey" (that is, it's a `string`, - * `number`, `boolean`, `bigint`, `null` or `undefined`), the properties will - * be appended as strings, formatted as - * `{{property_name}}: {{property_value}}` and joined with "`\n`". - * - * If the `accumulator` property is an array, the properties will be appended - * as array items, formatted as `{{property_name}}: {{property_value}}`. - * - * Otherwise, the `accumulator` property will be treated as an object and - * the properties will be added as properties on this object. - * - * See [`append` node reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/core-kit/README.md) for more information. - * - */ - append, - - /** - * Work-in-progress implementation of the `map` node. - * See #127 for more information. - */ - map, - reduce, - batch, - fetch, - runJavascript, - secrets, - curry, - - /** - * Converts all inline data to stored data, saving memory. - * Useful when working with multimodal content. Safely passes - * data through if it's already stored or no inline data is - * present. - */ - deflate, - inflate, - - unnest: unnestNode, - cast: castNode, - - service, - - storeData: storeDataNode, - retrieveData: retrieveDataNode, -}); - -export type Core = InstanceType; - -export default Core; - -/** - * This is a wrapper around existing kits for the new syntax to add types. - * - * This should transition to a codegen step, with typescript types constructed - * from .describe() calls. - */ -import { kit, NodeFactoryFromDefinition } from "@breadboard-ai/build"; -import { - addKit, - NewInputValues as InputValues, - NewNodeFactory as NodeFactory, - NewNodeValue as NodeValue, - NewOutputValues as OutputValues, -} from "@google-labs/breadboard"; -import curry from "./nodes/curry.js"; -import deflate from "./nodes/deflate.js"; -import inflate from "./nodes/inflate.js"; - -export type CoreKitType = { - passthrough: NodeFactory; - /** - * Creates the `append` node, which can be used to accumulate local state, - * like context in a prompt. - * - * The node looks for property called `accumulator` in its input. All other - * properties are appended to this property, and returned as `accumulator` - * output property. - * - * The way the properties are appended depends on the type of the - * `accumulator` input property. - * - * If the `accumulator` property is "string-ey" (that is, it's a `string`, - * `number`, `boolean`, `bigint`, `null` or `undefined`), the properties will - * be appended as strings, formatted as - * `{{property_name}}: {{property_value}}` and joined with "`\n`". - * - * If the `accumulator` property is an array, the properties will be appended - * as array items, formatted as `{{property_name}}: {{property_value}}`. - * - * Otherwise, the `accumulator` property will be treated as an object and - * the properties will be added as properties on this object. - * - * See [`append` node reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/core-kit/README.md) for more information. - * - */ - append: NodeFactory< - { accumulator: NodeValue; [key: string]: NodeValue }, - { accumulator: NodeValue } - >; - /** - * Creates an `invoke` node, which can be used invoke other boards within - * the current board. - * - * See [`include` node - * reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/breadboard/docs/nodes.md#include) - * for more information. - * - * Expects as input one of - * - `path`: A board to be loaded - * - `graph`: A graph (treated as JSON) - * - `board`: A {BreadboardCapability}, e.g. from lambda or import - * - * All other inputs are passed to the invoked board, - * and the output are the invoked board's outputs. - */ - invoke: NodeFactory< - { - /** - * A board to be invoked. - */ - $board: NodeValue; - [key: string]: NodeValue; - }, - { [key: string]: unknown } - >; - resolve: NodeFactory<{ [k: string]: string }, { [k: string]: string }>; - map: NodeFactory< - { - list: NodeValue[]; - board?: NodeValue; - }, - { list: NodeValue[] } - >; - reduce: NodeFactory< - { - /** - * The list to iterate over. - */ - list: unknown[]; - - /** - * The board to run for each element of the list. - */ - board?: unknown; - - /** - * The initial value for the accumulator. - */ - accumulator?: unknown; - }, - { - /** - * The current value of the accumulator. - */ - accumulator: NodeValue; - - /** - * The current item from the list. - */ - item: NodeValue; - } - >; - /** - * Combines a board with some arguments to create a new board (aka currying). - * The arguments in that board will run as part of board invocation as if - * they were supplied as inputs. - */ - curry: NodeFactory< - { - $board: unknown; - [key: string]: unknown; - }, - { - board: unknown; - } - >; - fetch: NodeFactory< - { url: string }, - { - response: string; - status: number; - statusText: string; - contentType?: string; - responseHeaders?: object; - } - >; - runJavascript: NodeFactory< - { - code: string; - name: string; - raw: boolean; - [key: string]: NodeValue; - }, - { result: unknown; [k: string]: unknown } - >; - secrets: NodeFactory<{ keys: string[] }, { [k: string]: string }>; - unnest: NodeFactoryFromDefinition; - cast: NodeFactoryFromDefinition; - // TODO: Other Core nodes. -}; - -/** - * The Core Kit. Use members of this object to create nodes to enable - * composition and reuse of in Breadboard. The most useful node is `invoke`, - * which allows you to invoke other boards within the current board. - * Another useful one is `map`, which allows you to map over a list of items - * and invoke a board for each item. - */ -export const core = addKit(Core) as unknown as CoreKitType; - -export const coreKit = await kit({ - ...metadata, - components: { - cast: castNode, - curry, - deflate, - fetch, - inflate, - invoke, - map, - passthrough, - reduce, - resolve, - runJavascript, - secrets, - service, - unnest: unnestNode, - storeData: storeDataNode, - retrieveData: retrieveDataNode, - }, -}); diff --git a/packages/core-kit/src/nodes/append.ts b/packages/core-kit/src/nodes/append.ts deleted file mode 100644 index 1026817083c..00000000000 --- a/packages/core-kit/src/nodes/append.ts +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - InputValues, - NodeDescriberFunction, - NodeHandler, - NodeValue, - OutputValues, - Schema, -} from "@google-labs/breadboard"; - -export enum ObjectType { - stringy, - array, - object, -} - -type AccumulatorType = string | string[] | Record; - -export type AppendInputs = Record & { - accumulator: AccumulatorType; -}; - -export type AppendOutputs = { - accumulator: AccumulatorType; -}; - -export const getObjectType = (value: unknown): ObjectType => { - if (value === null || value === undefined) return ObjectType.stringy; - const type = typeof value; - if (["string", "number", "boolean", "bigint"].includes(type)) - return ObjectType.stringy; - if (Array.isArray(value)) return ObjectType.array; - return ObjectType.object; -}; - -const asString = (values: NodeValue): string => { - if (getObjectType(values) == ObjectType.stringy) return String(values); - return Object.entries(values as Record) - .map(([k, v]) => { - const value = - getObjectType(v) === ObjectType.stringy ? v : JSON.stringify(v); - return `${k}: ${value}`; - }) - .join("\n"); -}; - -export const computeInputSchema = (incomingWires: Schema): Schema => { - type SchemaProperties = Schema["properties"]; - const properties: SchemaProperties = { - accumulator: { - title: "accumulator", - description: - "A string, an object, or an array to which other input values will be appended.", - type: ["array", "object", "string"], - items: { type: "string" }, - }, - }; - const inputSchema = { properties, additionalProperties: true }; - - if (!incomingWires.properties) return inputSchema; - - Object.entries(incomingWires.properties).forEach(([propertyName, schema]) => { - properties[propertyName] = schema; - }); - return inputSchema; -}; - -export const flattenValues = (values: InputValues) => { - let result: InputValues = {}; - Object.entries(values).forEach(([key, value]) => { - if (key === "$flatten" && getObjectType(value) == ObjectType.object) { - result = { ...result, ...(value as object) }; - } else { - result[key] = value; - } - }); - return result; -}; - -export const appendDescriber: NodeDescriberFunction = async ( - _inputs?: InputValues, - incomingWires?: Schema -) => { - const inputSchema = computeInputSchema(incomingWires || {}); - return { - inputSchema, - outputSchema: { - properties: { - accumulator: { - title: "accumulator", - description: - "The result of appending. This is input `accumulator` with the provided values appended to it.", - }, - }, - }, - }; -}; - -export default { - metadata: { - deprecated: true, - }, - describe: appendDescriber, - invoke: async (inputs: InputValues): Promise => { - const { accumulator, ...values } = inputs as AppendInputs; - if (Object.keys(values).length === 0) return { accumulator }; - const type = getObjectType(accumulator); - switch (type) { - case ObjectType.stringy: { - const stringy = - accumulator === null || accumulator === undefined - ? "" - : `${accumulator}\n`; - return { accumulator: `${stringy}${asString(values)}` }; - } - case ObjectType.array: { - const flattenedValues = flattenValues(values); - return { - accumulator: [...(accumulator as string[]), flattenedValues], - }; - } - case ObjectType.object: - return { - accumulator: { - ...(accumulator as object), - ...values, - }, - }; - } - }, -} satisfies NodeHandler; diff --git a/packages/core-kit/src/nodes/batch.ts b/packages/core-kit/src/nodes/batch.ts deleted file mode 100644 index 9e77a86e0ca..00000000000 --- a/packages/core-kit/src/nodes/batch.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - InputValues, - NodeHandlerObject, - NodeValue, - OutputValues, -} from "@google-labs/breadboard"; - -export type BatcherInputs = InputValues & { - /** - * The list to iterate over. - */ - list: NodeValue[]; - /** - * The size of each batch. - */ - size: number; -}; - -export type BatcherOutputs = InputValues & { - /** - * List of lists that batched into the specified size. - */ - list: NodeValue[]; -}; - -export default { - metadata: { - deprecated: true, - }, - invoke: async (inputs: InputValues): Promise => { - const { list, size } = inputs as BatcherInputs; - if (!list) throw new Error("Batcher requires `list` input"); - if (!size) throw new Error("Batcher requires `size` input"); - if (!list.length) return { list: [[]] }; - const batches = []; - for (let i = 0; i < list.length; i += size) { - batches.push(list.slice(i, i + size)); - } - return { list: batches }; - }, -} satisfies NodeHandlerObject; diff --git a/packages/core-kit/src/nodes/cast.ts b/packages/core-kit/src/nodes/cast.ts deleted file mode 100644 index f363470c7ed..00000000000 --- a/packages/core-kit/src/nodes/cast.ts +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - defineNodeType, - object, - toJSONSchema, - unsafeCast, - unsafeType, -} from "@breadboard-ai/build"; -import { type OutputPortReference } from "@breadboard-ai/build/internal/common/port.js"; -import type { - BreadboardType, - ConvertBreadboardType, - JsonSerializable, -} from "@breadboard-ai/build/internal/type-system/type.js"; - -/** - * Cast a value to the given JSON schema. - */ -export function cast( - value: OutputPortReference, - type: B -): OutputPortReference> { - return unsafeCast( - castNode({ value, type: toJSONSchema(type) }).unsafeOutput("value"), - type - ); -} - -/** - * Cast a value to the given JSON schema. - * - * When using TypeScript, prefer the {@link cast} function which also provides - * compile-time type-checking. - */ -export const castNode = defineNodeType({ - name: "cast", - metadata: { - title: "Cast", - description: "Cast a value to the given JSON schema.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-cast-component", - }, - }, - inputs: { - value: { - type: "unknown", - description: "The value to cast", - primary: true, - }, - type: { - type: object({}, "unknown"), - description: "The JSON schema to cast the value to", - behavior: ["json-schema"], - }, - }, - outputs: { - // TODO(aomarks) It's not currently possible to say "there is always a value - // port, but we don't know what the type is until later". - "*": { - type: "unknown", - }, - }, - describe: ({ type }) => { - return { - outputs: { - value: { - type: type ? unsafeType(type) : "unknown", - }, - }, - }; - }, - invoke: ({ value }) => ({ value }), -}); diff --git a/packages/core-kit/src/nodes/code.ts b/packages/core-kit/src/nodes/code.ts deleted file mode 100644 index ddb4e1a85c3..00000000000 --- a/packages/core-kit/src/nodes/code.ts +++ /dev/null @@ -1,246 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - extractTypeFromValue, - toJSONSchema, - type Value, -} from "@breadboard-ai/build"; -import type { OutputPort } from "@breadboard-ai/build/internal/common/port.js"; -import type { Expand } from "@breadboard-ai/build/internal/common/type-util.js"; -import type { Instance } from "@breadboard-ai/build/internal/define/instance.js"; -import type { - BreadboardType, - ConvertBreadboardType, - JsonSerializable, -} from "@breadboard-ai/build/internal/type-system/type.js"; -import runJavascript from "./run-javascript.js"; -import type { Convergence } from "@breadboard-ai/build/internal/board/converge.js"; -import type { Loopback } from "@breadboard-ai/build/internal/board/loopback.js"; -import { StarInputs } from "@breadboard-ai/build/internal/board/star-inputs.js"; - -/** - * The `code` function creates a {@link runJavascript} Breadboard node in a - * type-safe manner. Usage: - * - * ```ts - * import {code} from "@google-labs/core-kit"; - * import {board, input} from "@breadboard-ai/build"; - * - * const forwards = input({ description: "A string to reverse" }); - * - * const reversed = code({ forwards }, { reversed: "string" }, ({ forwards }) => ({ - * reversed: str.split("").reverse().join(""), - * })); - * - * export board({forwards}, {reversed: reversed.outputs.reversed}); - * ``` - */ -export function code< - I extends Record< - string, - Value | StarInputs - >, - O extends Record, ->( - inputs: I, - // TODO(aomarks) We could make the `outputs` parameter optional, but we'd have - // to be careful with schema. What we'd need to do if `outputs` is missing is: - // - // 1. Infer the output ports from `ReturnType` instead of from `outputs`. - // - // 2. Return a node that has a magic `outputs` object. This `outputs` object - // would be a proxy that overloads `get` to automatically create output - // ports as they are accessed (same as what we do below, except deferred). - // - // 3. Deal with the fact that the runtime `type` of those ports will be too - // broad. It will be the base dynamic output type of `runJavascript`, which - // is any JSON serializable value. - // - // This is OK when wiring to an input port because input ports already know - // their schema, and TypeScript will take care of making sure we only wire - // it to the right place. - // - // However, if we want to use one of these outputs as a _board output_, we - // have a problem, since we need to write the schema to the output node - // configuration. So, we'll probably want to introduce a "weak typed" - // version of an `OutputPortReference`, which is accepted when wiring - // nodes, but NOT accepted when configuring board outputs. Then, we can - // update the `output` utility function to only take weak - // `OutputPortReferences` if the `output` has had its type explicitly - // specified. - // - outputs: O, - fn: ( - params: Expand> - ) => - | Expand> - | { $error: string | { message: string } } - | Promise>> - | Promise<{ $error: string | { message: string } }> -): CodeNode>, ConvertBreadboardTypes> { - // TODO(aomarks) Do we need any of this logic involving function names? Why - // can't we just wrap the code in parens and invoke it like `()()`. - const id = inputs.$id as string | undefined; - const jsFriendlyId = id === undefined ? "run" : id.replace(/-/g, "_"); - const [code, name] = serializeFunction(jsFriendlyId, fn); - const node = runJavascript({ - code, - name, - raw: true, - inputSchema: { - type: "object", - properties: Object.fromEntries( - Object.entries(inputs) - .filter( - ([name]) => name !== "$id" && name !== "$metadata" && name !== "*" - ) - .map(([name, value]) => [ - name, - toJSONSchema(extractTypeFromValue(value)), - ]) - ), - ...(inputs["*"] !== undefined - ? { - additionalProperties: toJSONSchema( - extractTypeFromValue(inputs["*"]) - ), - } - : {}), - }, - outputSchema: { - type: "object", - properties: Object.fromEntries( - Object.entries(outputs).map(([name, output]) => [ - name, - toJSONSchema( - typeof output === "object" && "type" in output - ? output.type - : output - ), - ]) - ), - }, - ...(inputs as Record), - }) as CodeNode>, ConvertBreadboardTypes>; - for (const [name, type] of Object.entries(outputs)) { - // TODO(aomarks) This is a bit of a hacky way to materialize the dynamic - // ports. Node definitions should probably have a more elegant way to - // configure dynamic ports at instantiation time. - const port = node.unsafeOutput(name); - (port as Writable).type = - // TODO(aomarks) Need to also handle the undefined case. This type matters - // in that it will determine what schema we write if this output is wired - // to a board output. - (type as CodeOutputConfig)["type"] ?? type; - (node.outputs as Record>)[name] = port; - } - // eslint-disable-next-line @typescript-eslint/ban-types - node.test = fn as Function as CodeNode< - Expand>, - ConvertBreadboardTypes - >["test"]; - return node; -} - -export type CodeNode< - I extends Record, - O extends Record, -> = ReturnType & - Instance< - { code: string; name: string; raw: boolean } & I, - O, - JsonSerializable, - false, - never, - false - > & { - test: ( - params: Expand> - ) => - | Expand - | { $error: string | { message: string } } - | Promise> - | Promise<{ $error: string | { message: string } }>; - }; - -export interface CodeOutputConfig { - type: BreadboardType; - optional?: true; -} - -type CodeNodeInputs< - I extends Record | StarInputs>, -> = { - [K in keyof I]: I[K] extends Value - ? T - : never; -}; - -type ConvertOutput = - T extends BreadboardType - ? ConvertBreadboardType - : // TODO(aomarks) Not sure why I need the extends or never check here - // given the constraint on T. Probably not enough to distinguish the two - // types? - T extends CodeOutputConfig - ? T["optional"] extends true - ? ConvertBreadboardType | undefined - : ConvertBreadboardType - : never; - -type StrictCodeFunctionParams< - I extends Record | StarInputs>, -> = { - [K in keyof I as K extends "*" - ? never - : K extends "$id" - ? never - : K extends "$metadata" - ? never - : K]: I[K] extends - | Convergence - | Loopback - | Value - ? T - : never; -} & (I["*"] extends StarInputs ? { [K: string]: X } : object); - -type ConvertBreadboardTypes< - T extends Record, -> = Expand }>>; - -type Optionalize = { - [K in keyof T as undefined extends T[K] ? never : K]: T[K]; -} & { - [K in keyof T as undefined extends T[K] ? K : never]?: T[K]; -}; - -type Writable = { -readonly [P in keyof T]: T[P] }; - -const serializeFunction = ( - name: string, - // eslint-disable-next-line @typescript-eslint/ban-types - handlerFn: Function -) => { - let code = handlerFn.toString(); - - const arrowFunctionRegex = /(?:async\s*)?(\w+|\([^)]*\))\s*=>\s*/; - const traditionalFunctionRegex = - /(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)\s*\{/; - - if (arrowFunctionRegex.test(code)) { - code = `const ${name} = ${code};`; - } else { - const match = traditionalFunctionRegex.exec(code); - if (match === null) throw new Error("Unexpected serialization: " + code); - else name = match[1] || name; - } - return [code, name]; -}; - -// eslint-disable-next-line @typescript-eslint/ban-types -type x = { foo: string } & {}; diff --git a/packages/core-kit/src/nodes/curry.ts b/packages/core-kit/src/nodes/curry.ts deleted file mode 100644 index 7c18b1493b3..00000000000 --- a/packages/core-kit/src/nodes/curry.ts +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - anyOf, - defineNodeType, - object, - unsafeSchema, -} from "@breadboard-ai/build"; -import { getGraphDescriptor, inspect } from "@google-labs/breadboard"; - -export default defineNodeType({ - name: "curry", - metadata: { - title: "Curry", - description: - "Takes a board and bakes in (curries) supplied arguments into it. Very useful when we want to invoke a board with the same arguments many times (like with `map`).", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-curry-component", - }, - }, - inputs: { - $board: { - title: "Board", - type: anyOf("string", object({}, "unknown")), - behavior: ["board"], - description: - "The board to curry. Can be a BoardCapability, a graph or a URL", - }, - "*": { - type: "unknown", - }, - }, - outputs: { - board: { - title: "Board", - type: object({}, "unknown"), - behavior: ["board"], - description: "The curried board as a graph descriptor", - }, - }, - describe: async ({ $board }, _args, context) => { - if ($board === undefined || context?.base === undefined) { - return { inputs: { "*": "unknown" } }; - } - let descriptor; - try { - descriptor = await getGraphDescriptor($board, context); - } catch { - // This is a describer, so it must always return some valid value. - } - if (descriptor === undefined) { - return { inputs: { "*": "unknown" } }; - } - const { inputSchema } = await inspect(descriptor).describe(); - return { - inputs: unsafeSchema({ - ...inputSchema, - // All inputs from the curried board should be optional, because - // currying only a partial set of inputs is expected. - required: [], - }), - }; - }, - invoke: async ({ $board }, args, context) => { - const graph = await getGraphDescriptor($board, context); - return { board: { ...graph, args } }; - }, -}); diff --git a/packages/core-kit/src/nodes/deflate.ts b/packages/core-kit/src/nodes/deflate.ts deleted file mode 100644 index 730478d2cb6..00000000000 --- a/packages/core-kit/src/nodes/deflate.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { defineNodeType, object } from "@breadboard-ai/build"; -import { NodeHandlerContext, deflateData } from "@google-labs/breadboard"; - -export default defineNodeType({ - name: "deflate", - metadata: { - title: "Deflate", - description: - "Converts all inline data to stored data, saving memory. Useful when working with multimodal content. Safely passes data through if it's already stored or no inline data is present.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-deflate-component", - }, - }, - inputs: { - data: { - type: object({}), - title: "Data", - description: "Data to deflate.", - }, - }, - outputs: { - data: { - type: object({}), - title: "Data", - description: "Deflated data.", - }, - }, - invoke: async ({ data }, _, { store }: NodeHandlerContext) => { - if (!store) { - throw new Error( - "Data store was not specified in run configuration, but is required for deflation." - ); - } - return { data: await deflateData(store, data) }; - }, -}); diff --git a/packages/core-kit/src/nodes/fetch.ts b/packages/core-kit/src/nodes/fetch.ts deleted file mode 100644 index 5ecb7fdbcee..00000000000 --- a/packages/core-kit/src/nodes/fetch.ts +++ /dev/null @@ -1,228 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - anyOf, - defineNodeType, - enumeration, - object, -} from "@breadboard-ai/build"; -import { JsonSerializable } from "@breadboard-ai/build/internal/type-system/type.js"; -import { - DataStore, - NodeHandlerContext, - StreamCapability, - asBlob, - inflateData, - isDataCapability, -} from "@google-labs/breadboard"; - -const serverSentEventTransform = () => - new TransformStream({ - transform(chunk, controller) { - const text = chunk.toString(); - const lines = text.split("\n"); - for (const line of lines) { - if (line.startsWith("data: ")) { - const data = line.slice(6); - let chunk; - try { - // Special case for OpenAI's API. - if (data === "[DONE]") continue; - chunk = JSON.parse(data); - } catch (e) { - // TODO: Handle this more gracefully. - chunk = data; - } - controller.enqueue(chunk); - } - } - }, - }); - -const createBody = async ( - body: unknown, - headers: Record, - store?: DataStore -) => { - if (!body) return undefined; - const contentType = headers["Content-Type"]; - if (contentType === "multipart/form-data") { - const values = body as Record; - // This is necessary to let fetch set its own content type. - delete headers["Content-Type"]; - const formData = new FormData(); - for (const key in values) { - const value = values[key]; - if (typeof value === "string") { - formData.append(key, value); - } else if (isDataCapability(value)) { - if ("inlineData" in value) { - formData.append(key, await asBlob(value)); - } else { - formData.append(key, await asBlob(value)); - } - } else { - formData.append(key, JSON.stringify(value)); - } - } - return formData; - } - const data = store ? await inflateData(store, body) : body; - return JSON.stringify(data); -}; - -export default defineNodeType({ - name: "fetch", - metadata: { - title: "Fetch", - description: - "A wrapper around `fetch` API. Use this node to fetch content from the Web.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-fetch-component", - }, - }, - inputs: { - url: { - description: "The URL to fetch", - title: "URL", - type: "string", - }, - method: { - title: "Method", - behavior: ["config"], - description: "The HTTP method to use", - type: enumeration("GET", "POST", "PUT", "DELETE"), - default: "GET", - }, - headers: { - title: "Headers", - description: "Headers to send with the request", - type: object({}, "string"), - default: {}, - }, - body: { - title: "Body", - description: "The body of the request", - type: "unknown", - optional: true, - }, - raw: { - title: "Raw", - behavior: ["config"], - description: - "Whether or not to return raw text (as opposed to parsing JSON)", - type: "boolean", - default: false, - }, - stream: { - title: "Stream", - behavior: ["config"], - description: "Whether or not to return a stream", - type: "boolean", - default: false, - }, - }, - outputs: { - response: { - title: "Response", - description: "The response from the fetch request", - type: "unknown", - primary: true, - }, - status: { - title: "Status", - description: "The HTTP status code of the response", - type: "number", - }, - statusText: { - title: "Status Text", - description: "The status text of the response", - type: "string", - }, - contentType: { - title: "Content Type", - description: "The content type of the response", - type: anyOf("string", "null"), - }, - responseHeaders: { - title: "Response Headers", - description: "The headers of the response", - type: object({}, "string"), - }, - }, - invoke: async ( - { url, method, body, headers, raw, stream }, - _, // No dynamic inputs. - { signal, store }: NodeHandlerContext - ) => { - if (!url) throw new Error("Fetch requires `url` input"); - const init: RequestInit = { method, headers, signal }; - // GET can not have a body. - if (method !== "GET") { - init.body = await createBody(body, headers, store); - } else if (body) { - throw new Error("GET requests can not have a body"); - } - const data = await fetch(url, init); - const status = data.status; - const responseHeaders: { [key: string]: string } = {}; - data.headers.forEach((value, name) => { - responseHeaders[name] = value; - }); - const contentType = data.headers.get("content-type"); - const statusText = data.statusText; - if (!data.ok) - return { - // TODO(aomarks) Figure out how to model errors better. - $error: await data.json(), - status, - statusText, - contentType, - responseHeaders, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any; - if (stream) { - if (!data.body) { - throw new Error("Response is not streamable."); - } - return { - stream: new StreamCapability( - data.body - .pipeThrough(new TextDecoderStream()) - .pipeThrough(serverSentEventTransform()) - ), - // TODO(aomarks) Figure out how to model streaming responses better. - // For now we just cast the problem away and assume the runtime knows - // what to do. - // - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any; - } else { - let response; - if (!contentType) { - response = await data.text(); - } else { - const isJson = contentType?.includes("application/json"); - const isText = contentType?.startsWith("text/"); - if (isJson) { - response = raw ? await data.text() : await data.json(); - } else if (isText) { - response = await data.text(); - } else { - if (!store) { - throw new Error( - "No store provided in run configuration to store the response." - ); - } - const blob = await data.blob(); - response = await store.store(blob); - } - } - return { response, status, statusText, contentType, responseHeaders }; - } - }, -}); diff --git a/packages/core-kit/src/nodes/import.ts b/packages/core-kit/src/nodes/import.ts deleted file mode 100644 index 3b75b9dece0..00000000000 --- a/packages/core-kit/src/nodes/import.ts +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { SchemaBuilder } from "@google-labs/breadboard/kits"; -import type { - InputValues, - BreadboardCapability, - NodeHandlerContext, - GraphDescriptor, - OutputValues, -} from "@google-labs/breadboard"; -import { loadGraphFromPath } from "../utils.js"; - -export type ImportNodeInputs = InputValues & { - path?: string; - graph?: GraphDescriptor; - args: InputValues; -}; - -export default { - metadata: { - deprecated: true, - }, - 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 => { - const { path, graph, ...args } = inputs as ImportNodeInputs; - - const board = graph - ? graph - : path - ? await loadGraphFromPath(path, context) - : undefined; - if (!board) throw Error("No board provided"); - board.args = args; - - return { board: { kind: "board", board } as BreadboardCapability }; - }, -}; diff --git a/packages/core-kit/src/nodes/include.ts b/packages/core-kit/src/nodes/include.ts deleted file mode 100644 index d7dfcb99ac3..00000000000 --- a/packages/core-kit/src/nodes/include.ts +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - InputValues, - OutputValues, - BreadboardSlotSpec, - NodeHandlerContext, - BreadboardCapability, - GraphDescriptor, -} from "@google-labs/breadboard"; -import { getGraphDescriptor, invokeGraph } from "@google-labs/breadboard"; -import { SchemaBuilder } from "@google-labs/breadboard/kits"; -import { loadGraphFromPath } from "../utils.js"; - -export type IncludeNodeInputs = InputValues & { - path?: string; - $ref?: string; - board?: BreadboardCapability; - graph?: GraphDescriptor; - slotted?: BreadboardSlotSpec; - args: InputValues; -}; - -export default { - metadata: { - deprecated: true, - }, - 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 => { - 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.base?.href, ...slotted[key] }; - } - } - - // TODO: Please fix the $ref/path mess. - const source = path || $ref || ""; - - const runnableBoard = board - ? await getGraphDescriptor(board, context) - : graph - ? graph - : await loadGraphFromPath(source, context); - - if (!runnableBoard) { - throw new Error("Must provide valid board to include"); - } - - return await invokeGraph(runnableBoard, args, context); - }, -}; diff --git a/packages/core-kit/src/nodes/inflate.ts b/packages/core-kit/src/nodes/inflate.ts deleted file mode 100644 index 5e742aa44a2..00000000000 --- a/packages/core-kit/src/nodes/inflate.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { defineNodeType, object } from "@breadboard-ai/build"; -import { NodeHandlerContext, inflateData } from "@google-labs/breadboard"; - -export default defineNodeType({ - name: "inflate", - metadata: { - title: "Inflate", - description: "Converts stored data to base64.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-inflate-component", - }, - }, - inputs: { - data: { - type: object({}), - title: "Data", - description: "Data to inflate.", - }, - }, - outputs: { - data: { - type: object({}), - title: "Data", - description: "inflated data.", - }, - }, - invoke: async ({ data }, _, { store }: NodeHandlerContext) => { - if (!store) { - throw new Error( - "Data store was not specified in run configuration, but is required for inflation." - ); - } - return { data: await inflateData(store, data) }; - }, -}); diff --git a/packages/core-kit/src/nodes/invoke.ts b/packages/core-kit/src/nodes/invoke.ts deleted file mode 100644 index 4da6b371ff7..00000000000 --- a/packages/core-kit/src/nodes/invoke.ts +++ /dev/null @@ -1,152 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - InputValues, - NodeHandlerContext, - BreadboardCapability, - GraphDescriptor, - NodeDescriberContext, -} from "@google-labs/breadboard"; -import { - getGraphDescriptor, - inspect, - invokeGraph, -} from "@google-labs/breadboard"; -import { getRunner, loadGraphFromPath } from "../utils.js"; -import { defineNodeType, object, unsafeSchema } from "@breadboard-ai/build"; - -export type InvokeNodeInputs = InputValues & { - $board?: string | BreadboardCapability | GraphDescriptor; - path?: string; - board?: BreadboardCapability; - graph?: GraphDescriptor; -}; - -type RunnableBoardWithArgs = { - board: GraphDescriptor | undefined; - args: InputValues; -}; - -const getRunnableBoard = async ( - context: NodeHandlerContext, - inputs: InvokeNodeInputs -): Promise => { - const { $board, ...args } = inputs; - if ($board) { - const board = await getRunner($board, context); - return { board, args }; - } else { - const { path, board, graph, ...args } = inputs as InvokeNodeInputs; - - let runnableBoard; - - if (board) { - runnableBoard = await getGraphDescriptor(board, context); - } else if (graph) { - runnableBoard = graph; - } else if (path) { - runnableBoard = await loadGraphFromPath(path, context); - } - return { board: runnableBoard, args }; - } -}; - -const describe = async ( - inputs?: InvokeNodeInputs, - context?: NodeDescriberContext -) => { - if (context?.base) { - let board: GraphDescriptor | undefined; - if (inputs) { - try { - board = (await getRunnableBoard(context, inputs)).board; - } catch { - // eat any exceptions. - // This is a describer, so it must always return some valid value. - } - if (board) { - const inspectableGraph = inspect(board, { - kits: context.kits, - loader: context.loader, - }); - const { inputSchema, outputSchema } = - await inspectableGraph.describe(inputs); - return { - inputs: unsafeSchema(inputSchema), - outputs: unsafeSchema(outputSchema), - }; - } - return { inputs: { "*": {} }, outputs: { "*": {} } }; - } - } - return { inputs: {}, outputs: {} }; -}; - -export default defineNodeType({ - name: "invoke", - metadata: { - title: "Invoke", - description: - "Invokes (runOnce) specified board, supplying remaining incoming wires as inputs for that board. Returns the outputs of the board.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-invoke-component", - }, - }, - inputs: { - path: { - title: "path", - behavior: ["deprecated"], - description: "The path to the board to invoke.", - type: "string", - optional: true, - }, - $board: { - title: "Board", - behavior: ["board", "config"], - description: - "The board to invoke. Can be a BoardCapability, a graph or a URL", - // TODO(aomarks) A better type. - type: object({}), - optional: true, - }, - "*": { - type: "unknown", - }, - }, - outputs: { - "*": { - type: "unknown", - }, - }, - describe: async (staticInputs, dynamicInputs, context) => { - // TODO(aomarks) Cast here because the type system doesn't understand - // BreadboardCapability or GraphDescriptors yet. - const inputs = { ...staticInputs, ...dynamicInputs } as InvokeNodeInputs; - return describe(inputs, context); - }, - invoke: async (staticInputs, dynamicInputs, context) => { - // TODO(aomarks) Cast here because the type system doesn't understand - // BreadboardCapability or GraphDescriptors yet. - const inputs = { ...staticInputs, ...dynamicInputs } as InvokeNodeInputs; - const { board, args } = await getRunnableBoard(context, inputs); - if (!board) { - console.warn("Could not get a runnable board"); - throw new Error("Could not get a runnable board"); - } - // If the current board has a URL, pass it as new base. - // Otherwise, use the previous base. - const base = context.board?.url && new URL(context.board?.url); - const invocationContext = base - ? { - ...context, - base, - } - : { ...context }; - - return await invokeGraph(board, args, invocationContext); - }, -}); diff --git a/packages/core-kit/src/nodes/map.ts b/packages/core-kit/src/nodes/map.ts deleted file mode 100644 index b229f253d80..00000000000 --- a/packages/core-kit/src/nodes/map.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { anyOf, array, defineNodeType, object } from "@breadboard-ai/build"; -import type { - BoardOutputPorts, - GenericBoardDefinition, -} from "@breadboard-ai/build/internal/board/board.js"; -import type { Input } from "@breadboard-ai/build/internal/board/input.js"; -import type { OutputPortReference } from "@breadboard-ai/build/internal/common/port.js"; -import type { Expand } from "@breadboard-ai/build/internal/common/type-util.js"; -import type { JsonSerializable } from "@breadboard-ai/build/internal/type-system/type.js"; -import { - getGraphDescriptor, - GraphDescriptor, - invokeGraph, - NodeHandlerContext, - OutputValues, -} from "@google-labs/breadboard"; - -/** - * Apply the given board to all elements of the given array-type Breadboard - * value. - */ -export function map( - list: OutputPortReference>, - board: GenericBoardDefinition & { - inputs: { - item: Input; - }; - outputs: O; - } -): OutputPortReference>>> { - return mapNode({ list, board }).outputs.list; -} - -type ExtractOutputTypes = { - [K in keyof B]: B[K] extends OutputPortReference - ? T extends undefined - ? never - : T - : never; -}; - -const invokeGraphPerItem = async ( - graph: GraphDescriptor, - item: JsonSerializable, - index: number, - list: JsonSerializable, - context: NodeHandlerContext -) => { - // If the current board has a URL, pass it as new base. - // Otherwise, use the previous base. - const base = context?.board?.url && new URL(context.board?.url); - - const newContext = { - ...context, - base: base || context?.base, - invocationPath: [...(context?.invocationPath || []), index], - }; - const outputs = await invokeGraph(graph, { item, index, list }, newContext); - // TODO(aomarks) Map functions have an "item" input, but not an "item" - // output. Instead, all outputs become the map result. That's a bit - // weird, since it means you can't e.g. map a string to a string; only a - // string to an object containing a string. Let's try and migrate to a - // symmetrical map type, will need an opt-in flag initially. - return outputs; -}; - -const mapNode = defineNodeType({ - name: "map", - metadata: { - title: "Map", - description: - "Given a list and a board, iterates over this list (just like your usual JavaScript `map` function), invoking (runOnce) the supplied board for each item.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-map-component", - }, - }, - inputs: { - list: { - title: "List", - type: array("unknown"), - }, - board: { - title: "Board", - type: anyOf( - "string", - // TODO(aomarks) An embedded board. Should have a better schema to use - // here. Maybe with a JSON schema ID reference? - object({}, "unknown") - ), - // TODO(aomarks) There should alsobe a way to specify what the interface of - // the board must be. - behavior: ["board"], - description: "The board to run for each element of the list.", - }, - }, - outputs: { - list: { - title: "List", - type: array(object({}, "unknown")), - description: "The list of outputs from the board.", - }, - }, - invoke: async ({ list, board }, _, context) => { - // TODO(aomarks) Don't support this use case, just require an array. - if (typeof list === "string") { - try { - list = JSON.parse(list); - } catch (e) { - throw new Error( - `List was a string, tried and failed parsing it as JSON: ${list}` - ); - } - } - if (!Array.isArray(list)) { - // TODO(aomarks) This should get automatically detected and we shouldn't - // be able to even get to invoke. We know the JSON schema up-front. - throw new Error(`Expected list to be an array, but got ${list}`); - } - const graph = await getGraphDescriptor(board, context); - if (!graph) return { list }; - let result: OutputValues[]; - const runSerially = !!context.state; - if (runSerially) { - result = []; - for (const [index, item] of list.entries()) { - result.push( - await invokeGraphPerItem(graph, item, index, list, context) - ); - } - } else { - result = await Promise.all( - list.map(async (item, index) => { - return invokeGraphPerItem(graph, item, index, list, context); - }) - ); - } - - const errors = result.filter((r) => r.$error); - if (errors.length === 0) { - // Easy case, no errors. Just return the list. - return { list: result }; - } - // Return first error. - // TODO: Implement showing multiple errors. - // TODO: Consider returning the list of results, with errors in place. - // This would allow the user to see the results of the successful runs. - return { $error: errors[0].$error }; - }, -}); -export default mapNode; diff --git a/packages/core-kit/src/nodes/passthrough.ts b/packages/core-kit/src/nodes/passthrough.ts deleted file mode 100644 index dd8db083bf9..00000000000 --- a/packages/core-kit/src/nodes/passthrough.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { defineNodeType } from "@breadboard-ai/build"; - -export default defineNodeType({ - name: "passthrough", - metadata: { - title: "Passthrough", - description: - "Takes all inputs and passes them through as outputs. Effectively, a no-op node in Breadboard.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-passthrough-component", - }, - }, - inputs: { - "*": { - type: "unknown", - }, - }, - outputs: { - "*": { - type: "unknown", - reflective: true, - }, - }, - invoke: (_, inputs) => inputs, -}); diff --git a/packages/core-kit/src/nodes/reduce.ts b/packages/core-kit/src/nodes/reduce.ts deleted file mode 100644 index edf4c50e409..00000000000 --- a/packages/core-kit/src/nodes/reduce.ts +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { array, defineNodeType, object } from "@breadboard-ai/build"; -import { JsonSerializable } from "@breadboard-ai/build/internal/type-system/type.js"; -import { invokeGraph } from "@google-labs/breadboard"; -import { getRunner } from "../utils.js"; - -export default defineNodeType({ - name: "reduce", - metadata: { - title: "Reduce", - description: - "Given a list, an initial accumulator value, and a board, invokes a board (runOnce) for each item and accumulator in the list and returns the final accumulator value. Loosely, same logic as the `reduce` function in JavaScript.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-reduce-component", - }, - }, - inputs: { - list: { - title: "List", - type: array("unknown"), - description: "The list to iterate over.", - }, - board: { - title: "Board", - type: object({}, "unknown"), - behavior: ["board"], - description: "The board to run for each element of the list.", - }, - accumulator: { - title: "Accumulator", - type: "unknown", - description: "The initial value for the accumulator.", - }, - }, - outputs: { - accumulator: { - title: "Accumulator", - type: "unknown", - description: "The final value of the accumulator.", - }, - }, - invoke: async ({ list, board, accumulator }, _, context) => { - if (!Array.isArray(list)) { - throw new Error(`Expected list to be an array, but got ${list}`); - } - const runnableBoard = await getRunner(board, context); - if (!runnableBoard) return { accumulator }; - let result = accumulator; - let index = 0; - for (const item of list) { - const newContext = { - ...context, - invocationPath: [...(context?.invocationPath || []), index++], - }; - const { accumulator } = await invokeGraph( - runnableBoard, - { item, accumulator: result }, - newContext - ); - result = accumulator as JsonSerializable; - } - return { accumulator: result }; - }, -}); diff --git a/packages/core-kit/src/nodes/reflect.ts b/packages/core-kit/src/nodes/reflect.ts deleted file mode 100644 index 7997a0f6fda..00000000000 --- a/packages/core-kit/src/nodes/reflect.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - NodeHandlerContext, - GraphDescriptor, - InputValues, - OutputValues, -} from "@google-labs/breadboard"; -import { SchemaBuilder } from "@google-labs/breadboard/kits"; - -const deepCopy = (graph: GraphDescriptor): GraphDescriptor => { - return JSON.parse(JSON.stringify(graph)); -}; - -export default { - metadata: { - deprecated: true, - }, - describe: async () => { - return { - inputSchema: SchemaBuilder.empty(), - outputSchema: new SchemaBuilder() - .addProperties({ - graph: { - title: "graph", - description: "The graph descriptor of the current board.", - type: "object", - }, - }) - .setAdditionalProperties(false) - .addRequired("graph") - .build(), - }; - }, - invoke: async ( - _inputs: InputValues, - context: NodeHandlerContext - ): Promise => { - const graph = context.board ? deepCopy(context.board) : {}; - return { graph }; - }, -}; diff --git a/packages/core-kit/src/nodes/resolve.ts b/packages/core-kit/src/nodes/resolve.ts deleted file mode 100644 index 76a95da05b1..00000000000 --- a/packages/core-kit/src/nodes/resolve.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { defineNodeType } from "@breadboard-ai/build"; -import type { - InputValues, - NodeHandlerContext, - OutputValues, -} from "@google-labs/breadboard"; - -export default defineNodeType({ - name: "resolve", - metadata: { - deprecated: true, - }, - inputs: { "*": { type: "unknown" } }, - outputs: { "*": { type: "unknown" } }, - describe: () => { - return { - inputs: { "*": { type: "unknown" } }, - outputs: { "*": { type: "unknown" } }, - }; - }, - invoke: ( - _, - inputs: InputValues, - context: NodeHandlerContext - ): OutputValues => { - const base = inputs.$base ?? context.base?.href; - if (!base) { - throw new Error( - `Resolve could not find a base URL. The $base input was undefined, ` + - `and so was the handler context base.` - ); - } - if (typeof base !== "string") { - throw new Error(`Resolve base must be a string, got ${typeof base}.`); - } - const resolved: Record = {}; - for (const [name, value] of Object.entries(inputs)) { - if (name === "$base") { - continue; - } - if (typeof value !== "string") { - throw new Error( - `Resolve requires string inputs. Input "${name}" had type "${typeof value}".` - ); - } - resolved[name] = new URL(value, base).href; - } - return resolved; - }, -}); diff --git a/packages/core-kit/src/nodes/retrieveData.ts b/packages/core-kit/src/nodes/retrieveData.ts deleted file mode 100644 index 792aee89120..00000000000 --- a/packages/core-kit/src/nodes/retrieveData.ts +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { defineNodeType, object, unsafeSchema } from "@breadboard-ai/build"; -import { Schema } from "@google-labs/breadboard"; - -export const retrieveDataNode = defineNodeType({ - name: "retrieveData", - metadata: { - title: "Retrieve Data", - description: "Retrieve a value that was previously stored.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-retrieve-data-component", - }, - tags: ["experimental"], - }, - inputs: { - schema: { - type: object({}, "unknown"), - title: "Schema", - description: "The schema of the data to retrieve.", - behavior: ["ports-spec", "config"], - }, - }, - outputs: { - "*": { - type: "unknown", - }, - $notFound: { - type: object({}, "unknown"), - title: "Not Found", - description: "The schema of keys that were not found.", - }, - }, - invoke: async ({ schema }, _, context) => { - const store = context.store; - if (!store) { - throw new Error("Unable to retrieve data: The data store not available."); - } - const properties = (schema as Schema)?.properties; - const keys = Object.keys(properties || {}); - if (!properties || keys.length === 0) { - throw new Error( - "Unable to retrieve data: no properties were specified in Schema." - ); - } - const notFound: [property: string, schema: Schema][] = []; - const values: Record = {}; - for (const key of keys) { - const result = await store.retrieveData(key); - if (!result.success) { - notFound.push([key, properties[key]]); - } else { - // TODO: Implement schema comparison. - values[key] = result.value; - } - } - - if (notFound.length > 0) { - return { - $notFound: { - properties: Object.fromEntries(notFound), - type: "object", - required: notFound.map(([key]) => key), - }, - ...values, - }; - } - return values; - }, - describe: async ({ schema }) => { - const outputs = schema ? unsafeSchema(schema) : { "*": "unknown" }; - return { - outputs, - }; - }, -}); diff --git a/packages/core-kit/src/nodes/run-javascript.ts b/packages/core-kit/src/nodes/run-javascript.ts deleted file mode 100644 index 02ff09d9bf8..00000000000 --- a/packages/core-kit/src/nodes/run-javascript.ts +++ /dev/null @@ -1,341 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - defineNodeType, - object, - unsafeSchema, - unsafeType, -} from "@breadboard-ai/build"; -import { JsonSerializable } from "@breadboard-ai/build/internal/type-system/type.js"; -import type { InputValues } from "@google-labs/breadboard"; -import { JSONSchema4 } from "json-schema"; - -const runner = (code: string, functionName: string, args: string) => { - // The addition of `globalThis.__name = () => {}` is to ensure that - // if the function is compiled with esbuild --keep-names, the added "__name" - // call does not cause a runtime error. - // See https://github.com/privatenumber/tsx/issues/113 and - // https://github.com/evanw/esbuild/issues/1031 for more details. - return `${code} - globalThis.__name = () => {}; - self.onmessage = async () => { - try { - self.postMessage({ - result: JSON.stringify((await ${functionName}(${args}))) - }); - } catch (e) { - self.postMessage({ - error: e.message - }) - } - }; - self.onerror = (e) => self.postMessage({ - error: e.message - })`; -}; - -// https://regex101.com/r/PeEmEW/1 -const stripCodeBlock = (code: string) => - code.replace(/(?:```(?:js|javascript)?\n+)(.*)(?:\n+```)/gms, "$1"); - -// Copied from "secrets.ts". -// TODO: Clean this up, this feels like a util of some sort. -type Environment = "node" | "browser" | "worker" | "serviceWorker"; - -export type ScriptRunner = (args: { - code: string; - functionName: string; - args: string; -}) => Promise; - -const environment = (): Environment => { - if (typeof globalThis.process !== "undefined") { - return "node"; - } - if (typeof globalThis.window !== "undefined") { - return "browser"; - } - if ( - "ServiceWorkerGlobalScope" in globalThis && - // @ts-expect-error -- ServiceWorkerGlobalScope is not defined. - globalThis instanceof ServiceWorkerGlobalScope - ) { - return "serviceWorker"; - } - return "worker"; -}; - -const runInNode: ScriptRunner = async ({ code, functionName, args }) => { - // TODO: This code does not work when used with esbuild. Esbuild provides - // the "require" function anyway, and then throws an error when trying to - // call it. Figure out what's the right thing to do here. - // let vm; - // if (typeof require === "function") { - // vm = require("node:vm"); - // } else { - // vm = await import(/*@vite-ignore*/ "node:vm"); - // } - const vm = await import("node:vm"); - const codeToRun = `${code}\n${functionName}(${args});`; - const context = vm.createContext({ console, structuredClone }); - const script = new vm.Script(codeToRun); - const result = await script.runInNewContext(context); - return JSON.stringify(result); -}; - -const runInServiceWorker: ScriptRunner = async ({ - code, - functionName, - args, -}) => { - // @vite-ignore - const body = `return (async function() { \n${code};\nreturn await ${functionName}(${args}) })();`; - // Very very sorry. - const f = new Function(body); - const result = await f(); - return JSON.stringify(result); -}; - -const runInBrowser = async ({ - code, - functionName, - args, -}: { - code: string; - functionName: string; - args: string; -}): Promise => { - const blob = new Blob([runner(code, functionName, args)], { - type: "text/javascript", - }); - - type WebWorkerResultType = "error" | "result"; - type WebWorkerResult = { - [x in WebWorkerResultType]: string; - }; - - const workerURL = URL.createObjectURL(blob); - const worker = new Worker(workerURL, { type: "module" }); - const result = new Promise((resolve, reject) => { - worker.onmessage = (e) => { - const data = e.data as WebWorkerResult; - if (data.result) { - resolve(data.result); - URL.revokeObjectURL(workerURL); - worker.terminate(); - return; - } else if (data.error) { - console.log("Error in worker", data.error); - reject(new Error(data.error)); - } - }; - worker.onerror = (e) => { - reject(new Error(e.message)); - }; - }); - worker.postMessage("please"); - return result; -}; - -export type RunJavascriptOutputs = Record & { - result: unknown; -}; - -export type RunJavascriptInputs = InputValues & { - code?: string; - name?: string; - raw?: boolean; - schema?: JsonSerializable; -}; - -export function convertToNamedFunction({ - funcStr, - name = DEFAULT_FUNCTION_NAME, - throwOnNameMismatch = false, -}: { - funcStr: string; - name?: string; - throwOnNameMismatch?: boolean; -}): string { - // Regular expressions to identify different types of functions - const arrowFuncRegex = /^\s*((?:\((?:.|\n)*?\)|\w+)\s*=>\s*((?:.|\n)*))$/; - const namedFuncRegex = /^\s*function\s+[A-Za-z0-9_$]+\s*\(/; - const anonymousFuncRegex = /^\s*function\s*\(/; - - // Check if it's an arrow function - if (arrowFuncRegex.test(funcStr)) { - let [args, body] = funcStr.split("=>").map((s) => s.trim()); - // Add parentheses around single argument if not present - if (!args.startsWith("(")) { - args = `(${args})`; - } - if (!body.startsWith("{")) { - // If the body is a single expression, enclose it in braces - body = `{ return ${body}; }`; - } - return `function ${name}${args} ${body}`; - } - // Check if it's a named function - else if (namedFuncRegex.test(funcStr)) { - if (throwOnNameMismatch) { - const match = funcStr.match(/function\s+([A-Za-z0-9_$]+)\s*\(/); - const existingFunctionName = match ? match[1] : null; - if (existingFunctionName !== name) { - throw new Error( - `Function name mismatch: ${existingFunctionName} !== ${name}` - ); - } - } - return funcStr.replace(namedFuncRegex, `function ${name}(`); - } - // Check if it's an anonymous function - else if (anonymousFuncRegex.test(funcStr)) { - return funcStr.replace(anonymousFuncRegex, `function ${name}(`); - } - // If it's not a recognizable function format - else { - // Do not throw, since it could be a function format that this helper - // does not yet handle. - // Could also be a named function already. - return funcStr; - } -} - -const DEFAULT_FUNCTION_NAME = "run"; -export const runJavascriptHandler = async ( - { code, name, raw }: RunJavascriptInputs, - args: InputValues -) => { - if (!code) throw new Error("Running JavaScript requires `code` input"); - code = stripCodeBlock(code); - name ??= DEFAULT_FUNCTION_NAME; - code = convertToNamedFunction({ funcStr: code, name }); - // A smart helper that senses the environment (browser or node) and uses - // the appropriate method to run the code. - const argsString = JSON.stringify(args); - const env: Environment = environment(); - - let runner: ScriptRunner; - - try { - if (env === "node") { - runner = runInNode; - } else if (env === "browser") { - runner = runInBrowser; - } else if (env === "serviceWorker") { - runner = runInServiceWorker; - } else { - throw new Error(`Unsupported environment: ${env}`); - } - const result = JSON.parse( - await runner({ code, functionName: name, args: argsString }) - ); - return raw ? result : { result }; - } catch (e) { - // Remove everything outside eval from the stack trace - const stack = (e as Error).stack; - if (stack !== undefined) { - (e as Error).stack = stack - .split("\n") - .filter( - (line) => - !line.startsWith(" at") || - line.includes("evalmachine.") - ) - .join("\n"); - } - return { $error: { kind: "error", error: e } }; - } -}; - -export default defineNodeType({ - name: "runJavascript", - metadata: { - title: "Run Javascript", - description: "Runs supplied `code` input as Javascript.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-runjavascript-component", - }, - }, - inputs: { - code: { - description: "The JavaScript code to run", - title: "Code", - behavior: ["config", "code"], - format: "javascript", - type: "string", - }, - name: { - title: "Function Name", - description: - 'The name of the function to invoke in the supplied code. Default value is "run".', - type: "string", - behavior: ["config"], - default: "run", - }, - schema: { - behavior: ["config", "ports-spec", "deprecated"], - description: - "Deprecated! Please use inputSchema/outputSchema instead. The schema of the output data.", - type: object({}, "unknown"), - optional: true, - }, - inputSchema: { - title: "Input Schema", - description: "The schema of the input data, the function arguments.", - behavior: ["config", "ports-spec"], - type: object({}, "unknown"), - optional: true, - }, - outputSchema: { - title: "Output Schema", - behavior: ["config", "ports-spec"], - description: - "The schema of the output data, the shape of the object of the function return value.", - type: object({}, "unknown"), - optional: true, - }, - raw: { - title: "Raw Output", - behavior: ["config"], - description: - "Whether or not to return use the result of execution as raw output (true) or as a port called `result` (false). Default is false.", - type: "boolean", - default: false, - }, - "*": { - type: "unknown", - }, - }, - outputs: { - "*": { - type: "unknown", - }, - }, - describe: ({ raw, inputSchema, ...rest }) => { - // "schema" is the deprecated name for "outputSchema", so fall back to that. - const outputSchema: JSONSchema4 | undefined = - rest.outputSchema ?? rest.schema; - return { - inputs: inputSchema ? unsafeSchema(inputSchema) : { "*": "unknown" }, - outputs: raw - ? outputSchema - ? unsafeSchema(outputSchema) - : { "*": "unknown" } - : { - result: { - title: "Result", - description: "The result of running the JavaScript code", - type: outputSchema?.properties?.result - ? unsafeType(outputSchema.properties.result) - : "unknown", - }, - }, - }; - }, - invoke: (config, args) => runJavascriptHandler(config, args), -}); diff --git a/packages/core-kit/src/nodes/secrets.ts b/packages/core-kit/src/nodes/secrets.ts deleted file mode 100644 index f367cc1eeae..00000000000 --- a/packages/core-kit/src/nodes/secrets.ts +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { array, defineNodeType } from "@breadboard-ai/build"; - -type Environment = "node" | "browser" | "worker"; - -const environment = (): Environment => - typeof globalThis.process !== "undefined" - ? "node" - : typeof globalThis.window !== "undefined" - ? "browser" - : "worker"; - -export type SecretInputs = { - keys: string[]; -}; - -export type SecretWorkerResponse = { - type: "secret"; - data: string; -}; - -const getEnvironmentValue = (key: string) => { - const env = environment(); - if (env === "node") { - return process.env[key]; - } else if (env === "browser") { - // How do we avoid namespace clashes? - return globalThis.localStorage.getItem(key); - } else if (env === "worker") { - // TODO: Calling main thread is a general pattern, figure out a way to - // avoid a special call here. Maybe some Board util? - throw new Error( - "Secrets are not yet supported in workers. Please proxy these nodes to the main thread." - ); - } -}; - -export const requireNonEmpty = (key: string, value?: string | null) => { - if (!value) - throw new Error( - `Key "${key}" was not specified. Please check your environment and make sure it is set.` - ); - return value; -}; - -const getKeys = ( - inputs: { keys: string[] } = { keys: [] }, - safe: boolean -): string[] => { - const { keys } = inputs as SecretInputs; - if (typeof keys === "string") { - try { - return JSON.parse(keys); - } catch (e) { - const error = e as Error; - const message = `Error parsing keys: ${error.message}`; - if (safe) { - console.error(message); - return []; - } - throw new Error(message); - } - } - return keys; -}; - -const secrets = defineNodeType({ - name: "secrets", - metadata: { - title: "Secrets", - description: "Retrieves secret values, such as API keys.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-secrets-component", - }, - }, - inputs: { - keys: { - title: "Secrets", - description: "The array of secrets to retrieve from the node.", - type: array("string"), - behavior: ["config"], - }, - }, - outputs: { - "*": { - type: "string", - }, - }, - describe: (inputs) => ({ - outputs: inputs.keys ?? [], - }), - invoke: (inputs) => - Object.fromEntries( - getKeys(inputs, false).map((key) => [ - key, - requireNonEmpty(key, getEnvironmentValue(key)), - ]) - ), -}); -export default secrets; - -/** - * Create and configure a {@link secrets} node for one secret, and return the - * corresponding output port. - */ -export function secret(name: string) { - // TODO(aomarks) Should we replace the `secrets` node with a `secret` node - // that is monomorphic? Seems simpler. - return secrets({ - $id: `${name}-secret`, - keys: [name], - }).unsafeOutput(name); -} diff --git a/packages/core-kit/src/nodes/service.ts b/packages/core-kit/src/nodes/service.ts deleted file mode 100644 index de647153af6..00000000000 --- a/packages/core-kit/src/nodes/service.ts +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { defineNodeType, fromJSONSchema } from "@breadboard-ai/build"; -import { PortConfigMap } from "@breadboard-ai/build/internal/common/port.js"; -import { InputValues } from "@google-labs/breadboard"; - -export type ServiceDescriptionMap = Map< - string, - { inputs: PortConfigMap; outputs: PortConfigMap } ->; - -export type ServiceStaticInputs = { - $service?: string; -}; - -// TODO: This cache should be cleared periodically. -const cache: ServiceDescriptionMap = new Map(); - -const normalize = (serviceURL: string) => { - if (serviceURL.endsWith("/")) { - return serviceURL.slice(0, -1); - } - return serviceURL; -}; - -const describe = async ( - { $service }: ServiceStaticInputs, - dynamicInputs: InputValues -) => { - if (!$service || typeof $service !== "string") { - return { inputs: {}, outputs: {} }; - } - const service = normalize($service); - if (cache.has(service)) { - return cache.get(service)!; - } - const describeURL = `${service}/describe`; - try { - const schemas = await ( - await fetch(describeURL, { - method: "POST", - body: JSON.stringify({ ...dynamicInputs }), - }) - ).json(); - const inputs = fromJSONSchema(schemas?.inputSchema ?? {}); - const outputs = fromJSONSchema(schemas?.outputSchema ?? {}); - const result = { inputs, outputs }; - cache.set(service, result); - return result; - } catch { - // Eat any exceptions. - // This is a describer, and it must always return some valid value. - } - return { inputs: {}, outputs: {} }; -}; - -const invoke = async (inputs: InputValues, dynamicInputs: InputValues) => { - const { $service } = inputs; - if (!$service || typeof $service !== "string") { - throw new Error("Service URL is required."); - } - - const service = normalize($service); - const invokeURL = `${service}/invoke`; - return await ( - await fetch(invokeURL, { - method: "POST", - body: JSON.stringify(dynamicInputs), - }) - ).json(); -}; - -export default defineNodeType({ - name: "service", - metadata: { - title: "Service", - description: - "Represents an external service that can be used by the board.", - }, - inputs: { - $service: { - title: "Service URL", - description: "The URL of the service to use.", - behavior: ["config"], - type: "string", - }, - "*": { - type: "unknown", - }, - }, - outputs: { - "*": { - type: "unknown", - }, - }, - invoke, - describe, -}); diff --git a/packages/core-kit/src/nodes/slot.ts b/packages/core-kit/src/nodes/slot.ts deleted file mode 100644 index bc3c4c561bb..00000000000 --- a/packages/core-kit/src/nodes/slot.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - InputValues, - OutputValues, - NodeDescriptor, -} from "@google-labs/breadboard"; -import { SchemaBuilder } from "@google-labs/breadboard/kits"; - -export type SlotNodeInputs = { - slot: string; - parent: NodeDescriptor; -}; - -export default { - metadata: { - deprecated: true, - }, - describe: async (inputs?: InputValues) => ({ - inputSchema: new SchemaBuilder() - .setAdditionalProperties(true) - .addInputs(inputs) - .addProperty("slot", { - title: "slot", - description: "The slot to run.", - type: "string", - }) - .build(), - outputSchema: new SchemaBuilder().setAdditionalProperties(true).build(), - }), - invoke: async (): Promise => { - throw new Error("Slot node is deprecated."); - }, -}; diff --git a/packages/core-kit/src/nodes/storeData.ts b/packages/core-kit/src/nodes/storeData.ts deleted file mode 100644 index c681c681a2a..00000000000 --- a/packages/core-kit/src/nodes/storeData.ts +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - defineNodeType, - enumeration, - object, - unsafeSchema, -} from "@breadboard-ai/build"; -import { Schema } from "@google-labs/breadboard"; - -export const storeDataNode = defineNodeType({ - name: "storeData", - metadata: { - title: "Store Data", - description: "Store a value for later use.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-store-data-component", - }, - tags: ["experimental"], - }, - inputs: { - $schema: { - type: object({}, "unknown"), - title: "Schema", - description: "The schema of the data to store.", - behavior: ["ports-spec", "config"], - }, - $scope: { - type: enumeration("run", "session", "client"), - description: "The scope to store the data in.", - title: "Scope", - behavior: ["config"], - default: "session", - }, - "*": { - type: "unknown", - }, - }, - outputs: { - "*": { - type: "unknown", - }, - }, - invoke: async ({ $schema, $scope }, values, context) => { - const store = context.store; - if (!store) { - throw new Error("Unable to store data: The data store not available."); - } - const properties = ($schema as Schema)?.properties; - const entries = Object.entries(properties || {}); - if (!properties || entries.length === 0) { - throw new Error( - "Unable to store data: no properties were specified in Schema." - ); - } - for (const [key, propertySchema] of entries) { - const value = values[key] as object | null; - const result = await store.storeData(key, value, propertySchema, $scope); - if (!result.success) { - throw new Error(`Unable to store value "${key}": ${result.error}`); - } - } - return values; - }, - describe: async ({ $schema: schema }) => { - const inputs = schema ? unsafeSchema(schema) : { "*": "unknown" }; - return { inputs, outputs: inputs }; - }, -}); diff --git a/packages/core-kit/src/nodes/unnest.ts b/packages/core-kit/src/nodes/unnest.ts deleted file mode 100644 index 4d37e929aa3..00000000000 --- a/packages/core-kit/src/nodes/unnest.ts +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - defineNodeType, - object, - toJSONSchema, - unsafeCast, - unsafeSchema, - unsafeType, -} from "@breadboard-ai/build"; -import type { - OutputPort, - OutputPortReference, -} from "@breadboard-ai/build/internal/common/port.js"; -import type { JsonSerializable } from "@breadboard-ai/build/internal/type-system/type.js"; - -/** - * Expose all properties of the given JSON object as separate output ports. - */ -export function unnest( - nested: OutputPortReference -): { [K in keyof T]-?: OutputPort } { - const instance = unnestNode({ nested }); - const type = nested["__output"].type; - const schema = toJSONSchema(type); - if (schema.type !== "object") { - throw new Error( - `Expected schema.type to be "object" but was "${schema.type}"` - ); - } - const outputs = Object.fromEntries( - Object.entries(schema.properties ?? {}).map(([name, schema]) => { - return [ - name, - unsafeCast(instance.unsafeOutput(name), unsafeType(schema)), - ]; - }) - ); - return outputs as { [K in keyof T]-?: OutputPort }; -} - -/** - * Expose all properties of the given JSON object as separate output ports. - * - * When using TypeScript, prefer the {@link unnest} function which also provides - * compile-time type-checking. - */ -export const unnestNode = defineNodeType({ - name: "unnest", - metadata: { - title: "Unnest", - description: - "Expose all properties of the given JSON object as separate output ports.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/core/#the-unnest-component", - }, - }, - inputs: { - nested: { - type: object({}, "unknown"), - description: "The nested object", - primary: true, - }, - }, - outputs: { - "*": { - type: "unknown", - }, - }, - describe: async (_, __, context) => { - const nestedSchema = - await context?.wires.incoming["nested"]?.outputPort?.describe(); - return { - outputs: nestedSchema ? unsafeSchema(nestedSchema) : { "*": "unknown" }, - }; - }, - invoke: ({ nested }) => { - return nested; - }, -}); diff --git a/packages/core-kit/src/utils.ts b/packages/core-kit/src/utils.ts deleted file mode 100644 index 6e627f94172..00000000000 --- a/packages/core-kit/src/utils.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphDescriptor, - NodeHandlerContext, - Throttler, - getGraphDescriptor, -} from "@google-labs/breadboard"; - -export const loadGraphFromPath = async ( - path: string, - context: NodeHandlerContext -) => { - const graph = await context.loader?.load(path, context); - if (!graph) throw new Error(`Unable to load graph from "${path}"`); - return graph; -}; - -type GetGraphDescriptorThrottler = Throttler< - [unknown, NodeHandlerContext], - GraphDescriptor | undefined ->; - -const graphDescriptorCache = new Map(); - -export const getRunner = async ( - board: unknown, - context: NodeHandlerContext -) => { - let throttler; - if (!graphDescriptorCache.has(board)) { - throttler = new Throttler(getGraphDescriptor); - graphDescriptorCache.set(board, throttler); - } else { - throttler = graphDescriptorCache.get(board)!; - } - return throttler.call({}, board, context); -}; diff --git a/packages/core-kit/tests/append.ts b/packages/core-kit/tests/append.ts deleted file mode 100644 index 3092f3a9643..00000000000 --- a/packages/core-kit/tests/append.ts +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import append, { - ObjectType, - getObjectType, - computeInputSchema, -} from "../src/nodes/append.js"; - -test("getObjectType correctly recognizes various object types", (t) => { - t.is(getObjectType("string"), ObjectType.stringy); - t.is(getObjectType(["array"]), ObjectType.array); - t.is(getObjectType({ object: true }), ObjectType.object); - t.is(getObjectType(1), ObjectType.stringy); - t.is(getObjectType(1.1), ObjectType.stringy); - t.is(getObjectType(true), ObjectType.stringy); - t.is(getObjectType(BigInt(1)), ObjectType.stringy); - t.is(getObjectType(null), ObjectType.stringy); - t.is(getObjectType(undefined), ObjectType.stringy); -}); - -test("`append` correctly recognizes empty accumulator", async (t) => { - const invoke = append.invoke; - t.deepEqual(await invoke({ value: "string" }), { - accumulator: "value: string", - }); - t.deepEqual(await invoke({ accumulator: null, value: "string" }), { - accumulator: "value: string", - }); - t.deepEqual(await invoke({ accumulator: 0, value: "string" }), { - accumulator: "0\nvalue: string", - }); - t.deepEqual(await invoke({ accumulator: false, value: "string" }), { - accumulator: "false\nvalue: string", - }); - t.deepEqual(await invoke({ accumulator: "", value: "string" }), { - accumulator: "\nvalue: string", - }); -}); - -test("`append` correctly appends to various object types", async (t) => { - const invoke = append.invoke; - t.deepEqual(await invoke({ accumulator: "string", value: "string" }), { - accumulator: "string\nvalue: string", - }); - t.deepEqual(await invoke({ accumulator: "string", foo: "bar", baz: 1 }), { - accumulator: "string\nfoo: bar\nbaz: 1", - }); - t.deepEqual(await invoke({ accumulator: [], value: "string" }), { - accumulator: [{ value: "string" }], - }); - t.deepEqual(await invoke({ accumulator: ["test"], foo: "bar", baz: 1 }), { - accumulator: ["test", { foo: "bar", baz: 1 }], - }); - t.deepEqual(await invoke({ accumulator: {}, value: "string" }), { - accumulator: { value: "string" }, - }); - t.deepEqual( - await invoke({ accumulator: { test: true }, foo: "bar", baz: 1 }), - { - accumulator: { test: true, foo: "bar", baz: 1 }, - } - ); -}); - -test("`append` doesn't append when there are no values", async (t) => { - const invoke = append.invoke; - t.deepEqual(await invoke({ accumulator: "string" }), { - accumulator: "string", - }); - t.deepEqual(await invoke({ accumulator: [] }), { - accumulator: [], - }); - t.deepEqual(await invoke({ accumulator: {} }), { - accumulator: {}, - }); -}); - -test("`append` correctly stringifies non-stringy values", async (t) => { - const invoke = append.invoke; - t.deepEqual(await invoke({ accumulator: "string", value: ["string"] }), { - accumulator: 'string\nvalue: ["string"]', - }); - t.deepEqual( - await invoke({ accumulator: "string", value: { key: "string" } }), - { - accumulator: 'string\nvalue: {"key":"string"}', - } - ); -}); - -test("`computeInputSchema` reacts to incoming wires", (t) => { - { - const incomingWires = {}; - const inputSchema = computeInputSchema(incomingWires); - t.like(inputSchema, { - properties: { - accumulator: { - title: "accumulator", - }, - }, - }); - } - { - const incomingWires = { - properties: { - foo: { - title: "foo", - type: "string", - }, - }, - }; - const inputSchema = computeInputSchema(incomingWires); - t.like(inputSchema, { - properties: { - accumulator: { - title: "accumulator", - }, - foo: { - title: "foo", - type: "string", - }, - }, - }); - } -}); diff --git a/packages/core-kit/tests/batch.ts b/packages/core-kit/tests/batch.ts deleted file mode 100644 index 2c20e42da92..00000000000 --- a/packages/core-kit/tests/batch.ts +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import batcher from "../src/nodes/batch.js"; - -test("works with reasonable arguments", async (t) => { - const inputs = { - list: [1, 2, 3], - size: 2, - }; - const outputs = await batcher.invoke(inputs); - t.deepEqual(outputs, { - list: [[1, 2], [3]], - }); -}); - -test("handles unreasonable arguments", async (t) => { - { - const inputs = { - list: [], - size: 2, - }; - const outputs = await batcher.invoke(inputs); - t.deepEqual(outputs, { - list: [[]], - }); - } - { - const inputs = { - list: [1, 2], - size: 0, - }; - await t.throwsAsync(async () => await batcher.invoke(inputs)); - } - { - const inputs = {}; - await t.throwsAsync(async () => await batcher.invoke(inputs)); - } - { - const inputs = { - size: 100, - }; - await t.throwsAsync(async () => await batcher.invoke(inputs)); - } -}); diff --git a/packages/core-kit/tests/code_test.ts b/packages/core-kit/tests/code_test.ts deleted file mode 100644 index 7d6f5c45780..00000000000 --- a/packages/core-kit/tests/code_test.ts +++ /dev/null @@ -1,387 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/* eslint-disable @typescript-eslint/ban-ts-comment */ - -import { - board, - converge, - defineNodeType, - input, - loopback, - serialize, - starInputs, -} from "@breadboard-ai/build"; -import test from "ava"; -import { code } from "@google-labs/core-kit"; - -test("usage", (t) => { - const str = input(); - const num = input({ type: "number" }); - - t.throws(() => - // @ts-expect-error - code() - ); - - // $ExpectType CodeNode<{ str: string; num: number; }, { fwdStr: string; fwdNum: number; newBool: boolean; }> - const c = code( - { str, num }, - { fwdStr: "string", fwdNum: "number", newBool: "boolean" }, - ( - // $ExpectType { str: string; num: number; } - params - ) => { - return { - fwdStr: - // $ExpectType string - params.str, - fwdNum: - // $ExpectType number - params.num, - newBool: true, - }; - } - ); - - code( - { str, num }, - { fwdStr: "string", fwdNum: "number", newBool: "boolean" }, - // @ts-expect-error - () => { - return {}; - } - ); - - code( - { str, num }, - { fwdStr: "string", fwdNum: "number", newBool: "boolean" }, - // @ts-expect-error - () => { - return { - fwdStr: "foo", - fwdNum: 123, - newBool: "true", - }; - } - ); - - t.truthy( - // $ExpectType InputPort - c.inputs.code - ); - t.truthy( - // $ExpectType InputPort - c.inputs.str - ); - t.truthy( - // $ExpectType InputPort - c.inputs.num - ); - - t.truthy( - // $ExpectType OutputPort - c.outputs.fwdStr - ); - t.truthy( - // $ExpectType OutputPort - c.outputs.fwdNum - ); - t.truthy( - // $ExpectType OutputPort - c.outputs.newBool - ); - - t.is( - // @ts-expect-error - c.outputs.notReal, - undefined - ); - - t.pass(); -}); - -test("serialization", (t) => { - const str = input(); - const num = input({ type: "number" }); - - // $ExpectType Definition<{ num: number; }, { halfNum: number; }, undefined, undefined, never, false, false, false, { num: { board: false; }; }> - const otherNodeDef = defineNodeType({ - name: "other", - inputs: { - num: { type: "number" }, - }, - outputs: { - halfNum: { type: "number" }, - }, - invoke: ({ num }) => ({ halfNum: num / 2 }), - }); - - const codeResult = code( - { - str, - num, - bool: false, - $id: "customId", - $metadata: { - title: "Custom title", - description: "Custom description", - }, - }, - { - strLen: "number", - strReversed: "string", - doubleNum: "number", - not: "boolean", - }, - ({ str, num, bool }) => ({ - strLen: str.length, - strReversed: str.split("").reverse().join(""), - doubleNum: num * 2, - not: !bool, - }) - ); - - // $ExpectType OutputPort - codeResult.outputs.strReversed; - - otherNodeDef({ - // TODO(aomarks) This should be an error! - num: codeResult.outputs.strReversed, - }); - - const otherNode = otherNodeDef({ num: codeResult.outputs.doubleNum }); - - const bgl = serialize( - board({ - inputs: { str, num }, - outputs: { - out1: codeResult.outputs.strLen, - out2: codeResult.outputs.strReversed, - out3: codeResult.outputs.doubleNum, - out4: codeResult.outputs.not, - out5: otherNode.outputs.halfNum, - }, - }) - ); - t.deepEqual(bgl, { - edges: [ - { from: "customId", to: "other-0", out: "doubleNum", in: "num" }, - { from: "customId", to: "output-0", out: "doubleNum", in: "out3" }, - { from: "customId", to: "output-0", out: "not", in: "out4" }, - { from: "customId", to: "output-0", out: "strLen", in: "out1" }, - { from: "customId", to: "output-0", out: "strReversed", in: "out2" }, - { from: "input-0", to: "customId", out: "num", in: "num" }, - { from: "input-0", to: "customId", out: "str", in: "str" }, - { from: "other-0", to: "output-0", out: "halfNum", in: "out5" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { num: { type: "number" }, str: { type: "string" } }, - required: ["num", "str"], - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - out1: { type: "number" }, - out2: { type: "string" }, - out3: { type: "number" }, - out4: { type: "boolean" }, - out5: { type: "number" }, - }, - required: ["out1", "out2", "out3", "out4", "out5"], - }, - }, - }, - { - id: "customId", - type: "runJavascript", - configuration: { - bool: false, - code: 'const customId = ({ str, num, bool }) => ({\n strLen: str.length,\n strReversed: str.split("").reverse().join(""),\n doubleNum: num * 2,\n not: !bool,\n });', - name: "customId", - raw: true, - inputSchema: { - properties: { - bool: { - type: "boolean", - }, - num: { - type: "number", - }, - str: { - type: "string", - }, - }, - type: "object", - }, - outputSchema: { - type: "object", - properties: { - doubleNum: { - type: "number", - }, - not: { - type: "boolean", - }, - strLen: { - type: "number", - }, - strReversed: { - type: "string", - }, - }, - }, - }, - metadata: { title: "Custom title", description: "Custom description" }, - }, - { id: "other-0", type: "other", configuration: {} }, - ], - }); -}); - -test("can return error", (t) => { - code({}, { bar: "string" }, () => ({ $error: "oh no" })); - code({}, { bar: "string" }, () => ({ $error: { message: "oh no" } })); - - code({}, { bar: "string" }, () => ({ - // @ts-expect-error - $error: 123, - })); - code({}, { bar: "string" }, () => ({ - // @ts-expect-error - $error: {}, - })); - code({}, { bar: "string" }, () => ({ - $error: { - // @ts-expect-error - msg: "foo", - }, - })); - - t.pass(); -}); - -test("exotic inputs", (t) => { - code( - { - in1: - // $ExpectType Convergence - converge(input(), input({ type: "number" })), - in2: - // $ExpectType Loopback - loopback({ type: "boolean" }), - }, - { out: "string" }, - ({ in1, in2 }) => { - // $ExpectType string | number - in1; - // $ExpectType boolean - in2; - return { out: "foo" }; - } - ); - t.pass(); -}); - -test("can pass star ports with *", (t) => { - const nums = starInputs({ type: "number" }); - const foo = input(); - const sum = code( - { "*": nums, foo }, - { sum: "number" }, - ({ - // $ExpectType string - foo, - // $ExpectType { [x: string]: number; } - ...nums - }) => ({ - sum: - Object.values(nums).reduce((prev, cur) => prev + cur, 0) + Number(foo), - }) - ).outputs.sum; - const bgl = serialize( - board({ inputs: { foo, "*": nums }, outputs: { sum } }) - ); - t.deepEqual(bgl, { - edges: [ - { from: "input-0", to: "runJavascript-0", out: "*", in: "" }, - { from: "input-0", to: "runJavascript-0", out: "foo", in: "foo" }, - { from: "runJavascript-0", to: "output-0", out: "sum", in: "sum" }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - type: "object", - properties: { foo: { type: "string" } }, - required: ["foo"], - additionalProperties: { type: "number" }, - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { sum: { type: "number" } }, - required: ["sum"], - }, - }, - }, - { - id: "runJavascript-0", - type: "runJavascript", - configuration: { - code: - `const run = ({ \n // $` + - `ExpectType string\n foo, \n // $` + - `ExpectType { [x: string]: number; }\n ...nums }) => ({\n sum: Object.values(nums).reduce((prev, cur) => prev + cur, 0) + Number(foo),\n });`, - inputSchema: { - type: "object", - properties: { - foo: { type: "string" }, - }, - additionalProperties: { type: "number" }, - }, - name: "run", - outputSchema: { - type: "object", - properties: { sum: { type: "number" } }, - }, - raw: true, - }, - }, - ], - }); - t.pass(); -}); - -test("can invoke functions directly with 'test'", (t) => { - const num = input({ type: "number" }); - const increment = code({ num }, { incremented: "number" }, ({ num }) => ({ - incremented: num + 1, - })); - // $ExpectType { incremented: number; } | Promise<{ incremented: number; }> | { $error: string | { message: string; }; } | Promise<{ $error: string | { message: string; }; }> - const result = increment.test({ num: 3 }); - t.deepEqual(result, { incremented: 4 }); - t.pass(); -}); diff --git a/packages/core-kit/tests/convert-to-named-function.ts b/packages/core-kit/tests/convert-to-named-function.ts deleted file mode 100644 index 0bebe3a6d63..00000000000 --- a/packages/core-kit/tests/convert-to-named-function.ts +++ /dev/null @@ -1,170 +0,0 @@ -import test from "ava"; -import { convertToNamedFunction } from "../src/nodes/run-javascript.js"; - -test("converts arrow function to named function", (t) => { - // @ts-expect-error noImplicitAny - const arrowFunc = ((x, y) => x + y).toString(); - const expected = "function sum(x, y) { return x + y; }"; - const result = convertToNamedFunction({ funcStr: arrowFunc, name: "sum" }); - t.is(result, expected); -}); - -test("converts anonymous function to named function", (t) => { - // @ts-expect-error noImplicitAny - const anonFunc = function (x, y) { - return x + y; - }.toString(); - const expected = `function sum(x, y) { - return x + y; - }`; - const result = convertToNamedFunction({ funcStr: anonFunc, name: "sum" }); - t.is(result, expected); -}); - -test("keeps named function name if already named", (t) => { - // @ts-expect-error noImplicitAny - const namedFunc = function originalName(x, y) { - return x + y; - }.toString(); - const expected = `function sum(x, y) { - return x + y; - }`; - const result = convertToNamedFunction({ funcStr: namedFunc, name: "sum" }); - t.is(result, expected); -}); - -test.skip("throws error for invalid function format", (t) => { - const invalidFunc = "This is not a function"; - const error = t.throws(() => - convertToNamedFunction({ funcStr: invalidFunc, name: "sum" }) - ); - t.is(error?.message, "Invalid function format"); -}); - -test("converts stringified arrow function to named function", (t) => { - const arrowFunc = ((x: number, y: number) => x + y).toString(); - const expected = "function sum(x, y) { return x + y; }"; - const result = convertToNamedFunction({ funcStr: arrowFunc, name: "sum" }); - t.is(result, expected); -}); - -test("converts stringified anonymous function to named function", (t) => { - const anonFunc = function (x: number, y: number) { - return x + y; - }.toString(); - const expected = `function sum(x, y) { - return x + y; - }`; - const result = convertToNamedFunction({ funcStr: anonFunc, name: "sum" }); - t.is(result, expected); -}); - -test("keeps name of stringified named function", (t) => { - const namedFunc = function originalName(x: number, y: number) { - return x + y; - }.toString(); - const expected = `function sum(x, y) { - return x + y; - }`; - const result = convertToNamedFunction({ funcStr: namedFunc, name: "sum" }); - t.is(result, expected); -}); - -test("handles no arguments", (t) => { - const noArgFunc = (() => 42).toString(); - const expected = "function sum() { return 42; }"; - const result = convertToNamedFunction({ funcStr: noArgFunc, name: "sum" }); - t.is(result, expected); -}); - -test("handles single argument", (t) => { - // @ts-expect-error noImplicitAny - const singleArgFunc = ((x) => x * 2).toString(); - const expected = "function sum(x) { return x * 2; }"; - const result = convertToNamedFunction({ - funcStr: singleArgFunc, - name: "sum", - }); - t.is(result, expected); -}); - -test("handles multiple arguments", (t) => { - // @ts-expect-error noImplicitAny - const multiArgFunc = ((x, y) => x + y).toString(); - const expected = "function sum(x, y) { return x + y; }"; - const result = convertToNamedFunction({ funcStr: multiArgFunc, name: "sum" }); - t.is(result, expected); -}); - -test("handles default arguments", (t) => { - // @ts-expect-error noImplicitAny - const defaultArgFunc = ((x, y = 10) => x + y).toString(); - const expected = "function sum(x, y = 10) { return x + y; }"; - const result = convertToNamedFunction({ - funcStr: defaultArgFunc, - name: "sum", - }); - t.is(result, expected); -}); - -test("handles complex arguments", (t) => { - // @ts-expect-error noImplicitAny - const complexFuncString = ((x, { y, z } = { y: 1, z: 2 }) => - x + y + z).toString(); - const expected = - "function sum(x, { y, z } = { y: 1, z: 2 }) { return x + y + z; }"; - const result = convertToNamedFunction({ - funcStr: complexFuncString, - name: "sum", - }); - t.is(result, expected); -}); - -test("handles multiline functions", (t) => { - // @ts-expect-error noImplicitAny - const multilineFunc = ((x) => { - const y = 10; - return x + y; - }).toString(); - const expected = `function sum(x) { - const y = 10; - return x + y; - }`; - const result = convertToNamedFunction({ - funcStr: multilineFunc, - name: "sum", - }); - t.is(result, expected); -}); - -test("handles multiline functions with default arguments", (t) => { - // @ts-expect-error noImplicitAny - const multilineFunc = function (x) { - const y = 10; - return x + y; - }.toString(); - const expected = `function sum(x) { - const y = 10; - return x + y; - }`; - const result = convertToNamedFunction({ - funcStr: multilineFunc, - name: "sum", - }); - t.is(result, expected); -}); - -test("if throwOnNameMismatch is true, throws error for mismatched function name", async (t) => { - function foo() { - return 42; - } - const error = t.throws(() => - convertToNamedFunction({ - funcStr: foo.toString(), - name: "bar", - throwOnNameMismatch: true, - }) - ); - t.truthy(error); - t.truthy(error?.message.includes("Function name mismatch")); -}); diff --git a/packages/core-kit/tests/data/boards/map-throw-error.bgl.json b/packages/core-kit/tests/data/boards/map-throw-error.bgl.json deleted file mode 100644 index 33d0ec0dfe5..00000000000 --- a/packages/core-kit/tests/data/boards/map-throw-error.bgl.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "title": "Throw an Error in a Map", - "version": "0.0.1", - "nodes": [ - { - "id": "map-27574fe8", - "type": "map", - "metadata": { - "visual": { - "x": 50.000000000000014, - "y": -165, - "collapsed": false - } - }, - "configuration": { - "board": { - "kind": "board", - "path": "#3ed1e058-5fcf-4c30-b91e-abae6cb4794e" - } - } - }, - { - "id": "runJavascript-c3b85180", - "type": "runJavascript", - "metadata": { - "visual": { - "x": -166, - "y": -146, - "collapsed": false - }, - "title": "List Maker", - "logLevel": "debug" - }, - "configuration": { - "name": "run", - "code": "function() { return [ \"foo\", \"bar\" ]; }" - } - } - ], - "edges": [ - { - "from": "runJavascript-c3b85180", - "to": "map-27574fe8", - "out": "result", - "in": "list" - } - ], - "graphs": { - "3ed1e058-5fcf-4c30-b91e-abae6cb4794e": { - "title": "Throw Error", - "description": "A blank board. Use it as a starting point for your creations.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -82.00000000000003, - "y": -1, - "collapsed": false - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "null" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 300, - "y": -8, - "collapsed": false - } - } - }, - { - "id": "runJavascript-41b20d06", - "type": "runJavascript", - "metadata": { - "visual": { - "x": 56.99999999999997, - "y": -4, - "collapsed": false - }, - "title": "Error Thrower", - "logLevel": "debug" - }, - "configuration": { - "code": "function() { throw new Error(\"ERROR HAS BEEN THROWN!\"); }", - "name": "run" - } - } - ], - "edges": [ - { - "from": "runJavascript-41b20d06", - "to": "output", - "out": "result", - "in": "context" - }, - { - "from": "input", - "to": "runJavascript-41b20d06", - "out": "context", - "in": "context" - } - ] - } - } -} diff --git a/packages/core-kit/tests/data/resolve/invokee.json b/packages/core-kit/tests/data/resolve/invokee.json deleted file mode 100644 index 0e79320507a..00000000000 --- a/packages/core-kit/tests/data/resolve/invokee.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "nodes": [ - { - "id": "invokee-input", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "result": { - "default": "invokee-data" - } - } - } - } - }, - { - "id": "invoker-output", - "type": "output" - } - ], - "edges": [ - { - "from": "invokee-input", - "out": "result", - "to": "invoker-output", - "in": "result" - } - ] -} diff --git a/packages/core-kit/tests/data/resolve/main.json b/packages/core-kit/tests/data/resolve/main.json deleted file mode 100644 index 41cbf8b8d4a..00000000000 --- a/packages/core-kit/tests/data/resolve/main.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "nodes": [ - { - "id": "main-input", - "type": "input" - }, - { - "id": "main-output", - "type": "output" - }, - { - "id": "main-resolve", - "type": "resolve" - }, - { - "id": "main-invoke", - "type": "invoke", - "configuration": { - "path": "./subdir/invoker.json" - } - } - ], - "edges": [ - { - "from": "main-input", - "out": "next-path", - "to": "main-resolve", - "in": "next-path" - }, - { - "from": "main-resolve", - "out": "next-path", - "to": "main-invoke", - "in": "next-path" - }, - { - "from": "main-invoke", - "out": "result", - "to": "main-output", - "in": "result" - } - ] -} diff --git a/packages/core-kit/tests/data/resolve/subdir/invoker.json b/packages/core-kit/tests/data/resolve/subdir/invoker.json deleted file mode 100644 index f13c8419a97..00000000000 --- a/packages/core-kit/tests/data/resolve/subdir/invoker.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "nodes": [ - { - "id": "invoker-input", - "type": "input" - }, - { - "id": "invoker-output", - "type": "output" - }, - { - "id": "invoker-invoke", - "type": "invoke" - } - ], - "edges": [ - { - "from": "invoker-input", - "out": "next-path", - "to": "invoker-invoke", - "in": "path" - }, - { - "from": "invoker-invoke", - "out": "result", - "to": "invoker-output", - "in": "result" - } - ] -} diff --git a/packages/core-kit/tests/invoke.ts b/packages/core-kit/tests/invoke.ts deleted file mode 100644 index 96b7185211f..00000000000 --- a/packages/core-kit/tests/invoke.ts +++ /dev/null @@ -1,208 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import handler from "../src/nodes/invoke.js"; - -test("describe with no values and no context.base", async (t) => { - t.deepEqual(await handler.describe(), { - inputSchema: { - additionalProperties: false, - properties: { - $board: { - behavior: ["board", "config"], - description: - "The board to invoke. Can be a BoardCapability, a graph or a URL", - title: "Board", - type: "object", - additionalProperties: false, - properties: {}, - required: [], - }, - path: { - behavior: ["deprecated"], - description: "The path to the board to invoke.", - title: "path", - type: "string", - }, - }, - type: "object", - required: [], - }, - outputSchema: { - additionalProperties: false, - properties: {}, - type: "object", - required: [], - }, - }); -}); - -test("describe with context.base and no values", async (t) => { - t.deepEqual( - await handler.describe(undefined, undefined, undefined, { - base: new URL("http://example.com/"), - outerGraph: { nodes: [], edges: [] }, - wires: { incoming: {}, outgoing: {} }, - }), - { - inputSchema: { - properties: { - $board: { - behavior: ["board", "config"], - description: - "The board to invoke. Can be a BoardCapability, a graph or a URL", - title: "Board", - type: "object", - additionalProperties: false, - properties: {}, - required: [], - }, - path: { - behavior: ["deprecated"], - description: "The path to the board to invoke.", - title: "path", - type: "string", - }, - }, - type: "object", - required: [], - additionalProperties: true, - }, - outputSchema: { - properties: {}, - type: "object", - required: [], - additionalProperties: true, - }, - } - ); -}); - -test("describe with context.base and invalid $board", async (t) => { - t.deepEqual( - await handler.describe({ $board: "invalid.json" }, undefined, undefined, { - base: new URL("file://invalid/base"), - outerGraph: { nodes: [], edges: [] }, - wires: { incoming: {}, outgoing: {} }, - }), - { - inputSchema: { - properties: { - $board: { - behavior: ["board", "config"], - description: - "The board to invoke. Can be a BoardCapability, a graph or a URL", - title: "Board", - type: "object", - additionalProperties: false, - properties: {}, - required: [], - }, - path: { - behavior: ["deprecated"], - description: "The path to the board to invoke.", - title: "path", - type: "string", - }, - }, - type: "object", - required: [], - additionalProperties: true, - }, - outputSchema: { - properties: {}, - type: "object", - required: [], - additionalProperties: true, - }, - } - ); -}); - -test("describe with context.base and valid $board", async (t) => { - t.deepEqual( - await handler.describe( - { - $board: { - nodes: [ - { - type: "input", - id: "input-1", - configuration: { - schema: { - type: "object", - properties: { - invokedBoardInput: { type: "string" }, - }, - required: ["invokedBoardInput"], - }, - }, - }, - { - type: "output", - id: "output-1", - configuration: { - schema: { - type: "object", - properties: { - invokedBoardOutput: { type: "number" }, - }, - }, - }, - }, - ], - edges: [], - }, - }, - undefined, - undefined, - { - base: new URL("http://example.com/"), - outerGraph: { nodes: [], edges: [] }, - wires: { incoming: {}, outgoing: {} }, - } - ), - { - inputSchema: { - type: "object", - additionalProperties: false, - properties: { - $board: { - behavior: ["board", "config"], - description: - "The board to invoke. Can be a BoardCapability, a graph or a URL", - title: "Board", - type: "object", - additionalProperties: false, - properties: {}, - required: [], - }, - path: { - behavior: ["deprecated"], - description: "The path to the board to invoke.", - title: "path", - type: "string", - }, - invokedBoardInput: { - type: "string", - }, - }, - required: ["invokedBoardInput"], - }, - outputSchema: { - type: "object", - properties: { - invokedBoardOutput: { - type: "number", - }, - }, - required: [], - additionalProperties: false, - }, - } - ); -}); diff --git a/packages/core-kit/tests/map.ts b/packages/core-kit/tests/map.ts deleted file mode 100644 index 64dcece6208..00000000000 --- a/packages/core-kit/tests/map.ts +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import map from "../src/nodes/map.js"; -import { Capability, Board, invokeGraph } from "@google-labs/breadboard"; -import { Core } from "../src/index.js"; - -test("map with no board just outputs list", async (t) => { - const inputs = { - list: [1, 2, 3], - }; - const outputs = await map.invoke(inputs, {}); - t.deepEqual(outputs, { list: [1, 2, 3] }); -}); - -test("sending a real board to a map", async (t) => { - const fun = new Board(); - fun.input().wire("*->", fun.output()); - - const board = new Board(); - const core = board.addKit(Core); - const input = board.input(); - const map = core.map({ - board: { - kind: "board", - board: fun, - } as Capability, // TODO: Fix types. - }); - input.wire("list->", map); - map.wire("list->", board.output()); - const outputs = await invokeGraph( - board, - { list: [1, 2, 3] }, - { - kits: [core], - } - ); - t.deepEqual(outputs, { - list: [ - { index: 0, item: 1, list: [1, 2, 3] }, - { index: 1, item: 2, list: [1, 2, 3] }, - { index: 2, item: 3, list: [1, 2, 3] }, - ], - }); -}); diff --git a/packages/core-kit/tests/node/map.ts b/packages/core-kit/tests/node/map.ts deleted file mode 100644 index 341700f6d64..00000000000 --- a/packages/core-kit/tests/node/map.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert"; -import test, { describe } from "node:test"; - -import Core from "../../src/index.js"; -import { - ErrorObject, - InputValues, - OutputValues, - asRuntimeKit, -} from "@google-labs/breadboard"; -import { RunConfig, run } from "@google-labs/breadboard/harness"; - -type SimpleRunResult = { - output: OutputValues | null; - error: string | ErrorObject | null; -}; - -const runBoard = async ( - board: string, - inputs: InputValues -): Promise => { - const config: RunConfig = { - base: new URL(import.meta.url), - kits: [asRuntimeKit(Core)], - url: `../../../tests/data/boards/${board}`, - }; - for await (const result of run(config)) { - const { type } = result; - switch (type) { - case "input": { - result.reply({ inputs }); - break; - } - case "output": { - return { error: null, output: result.data.outputs }; - } - case "error": { - return { error: result.data.error, output: null }; - } - } - } - return { error: null, output: null }; -}; - -describe("map", () => { - test("correctly reports errors in invoked boards", async () => { - const result = await runBoard("map-throw-error.bgl.json", {}); - assert.ok(result.error !== null); - }); -}); diff --git a/packages/core-kit/tests/passthrough.ts b/packages/core-kit/tests/passthrough.ts deleted file mode 100644 index 5be461fd8a6..00000000000 --- a/packages/core-kit/tests/passthrough.ts +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import passthrough from "../src/nodes/passthrough.js"; - -test("pass through all values", async (t) => { - const inputs = { - str: "foo", - num: 123, - arr: [{ bool: true }], - }; - const actual = await passthrough.invoke(inputs, null as never); - const expected = inputs; - t.deepEqual(actual, expected); -}); - -test("describe with no parameters returns empty schemas", async (t) => { - const actual = await passthrough.describe(); - const expected = { - inputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - }, - outputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: false, - }, - }; - t.deepEqual(actual, expected); -}); - -test("describe uses input values to generate output schema", async (t) => { - const actual = await passthrough.describe( - { - str: "foo", - num: 123, - arr: [true], - }, - { - type: "object", - properties: { - str: { type: "string" }, - num: { type: "number" }, - arr: { type: "array", items: { type: "boolean" } }, - }, - }, - { - type: "object", - properties: { - ignored: { - type: "string", - }, - }, - } - ); - const expected = { - inputSchema: { - type: "object", - properties: { - str: { - title: "str", - type: "string", - }, - num: { - title: "num", - type: "number", - }, - arr: { - title: "arr", - type: "array", - items: { - type: "boolean", - }, - }, - }, - required: [], - additionalProperties: true, - }, - outputSchema: { - type: "object", - properties: { - str: { - title: "str", - type: "string", - }, - num: { - title: "num", - type: "number", - }, - arr: { - title: "arr", - type: "array", - items: { - type: "boolean", - }, - }, - }, - required: [], - additionalProperties: false, - }, - }; - t.deepEqual(actual, expected); -}); diff --git a/packages/core-kit/tests/reduce.ts b/packages/core-kit/tests/reduce.ts deleted file mode 100644 index 1d18405512d..00000000000 --- a/packages/core-kit/tests/reduce.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { board, input, serialize } from "@breadboard-ai/build"; -import { - asRuntimeKit, - createLoader, - invokeGraph, -} from "@google-labs/breadboard"; -import test from "ava"; -import Core, { code, coreKit } from "../src/index.js"; - -test("reduce with no board just outputs accumulator", async (t) => { - const inputs = { - list: [1, 2, 3], - accumulator: 0, - }; - const outputs = await coreKit.reduce.invoke(inputs, {}); - t.deepEqual(outputs, { accumulator: 0 }); -}); - -test("using reduce as part of a board", async (t) => { - const innerBoard = (() => { - const accumulator = input({ type: "number" }); - const item = input({ type: "number" }); - const adder = code( - { accumulator, item }, - { accumulator: "number" }, - ({ accumulator, item }) => { - const sum = (accumulator || 0) + (item || 0); - return { accumulator: sum }; - } - ); - return board({ - inputs: { accumulator, item }, - outputs: { accumulator: adder.outputs.accumulator }, - }); - })(); - - const outerBoard = (() => { - const value = input({ type: "number" }); - const reducer = coreKit.reduce({ - list: [1, 2, 3], - accumulator: value, - board: innerBoard, - }); - return board({ - inputs: { value }, - outputs: { value: reducer.outputs.accumulator }, - }); - })(); - - const result = await invokeGraph( - serialize(outerBoard), - { value: 4 }, - { kits: [asRuntimeKit(Core)], loader: createLoader() } - ); - t.falsy(result.$error); - t.is(result.value, 10); -}); diff --git a/packages/core-kit/tests/resolve.ts b/packages/core-kit/tests/resolve.ts deleted file mode 100644 index 4e2e149fbe4..00000000000 --- a/packages/core-kit/tests/resolve.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; -import { run } from "@google-labs/breadboard/harness"; -import { asRuntimeKit } from "@google-labs/breadboard"; -import Core, { core, coreKit } from "@google-labs/core-kit"; -import resolve from "../src/nodes/resolve.js"; -import { board, input, serialize } from "@breadboard-ai/build"; - -test("resolve resolves paths relative to the board base by default", async (t) => { - t.deepEqual( - await resolve.invoke( - { path: "./bar.json" }, - { base: new URL("http://example.com/graphs/foo.json") } - ), - { path: "http://example.com/graphs/bar.json" } - ); -}); - -test("resolve resolves paths relative to the $base input when provided", async (t) => { - t.deepEqual( - await resolve.invoke( - { - path: "./bar.json", - $base: "file://not/the/default/foo.json", - }, - { base: new URL("http://example.com/graphs/foo.json") } - ), - { path: "file://not/the/default/bar.json" } - ); -}); - -test("resolve resolves multiple input properties", async (t) => { - t.deepEqual( - await resolve.invoke( - { - bar: "./bar.json", - abc123: "./abc123.json", - }, - { base: new URL("http://example.com/graphs/foo.json") } - ), - { - bar: "http://example.com/graphs/bar.json", - abc123: "http://example.com/graphs/abc123.json", - } - ); -}); - -test("resolve does nothing with no inputs", async (t) => { - t.deepEqual( - await resolve.invoke( - {}, - { base: new URL("http://example.com/graphs/foo.json") } - ), - {} - ); -}); - -test("resolve can be used to fully qualify a path prior to passing to a graph with a different base", async (t) => { - const config = { - url: "../../tests/data/resolve/main.json", - base: new URL(import.meta.url), - kits: [asRuntimeKit(Core)], - }; - let output: string | undefined; - for await (const result of run(config)) { - if (result.type === "error") { - console.error(result.data.error); - t.fail(JSON.stringify(result.data.error, null, 2)); - } else if (result.type == "input" && result.data.node.id === "main-input") { - result.reply({ - inputs: { "next-path": "../../tests/data/resolve/invokee.json" }, - }); - } else if ( - result.type === "output" && - result.data.node.id === "main-output" - ) { - output = result.data.outputs.result?.toString(); - } - } - t.is(output, "invokee-data"); -}); - -test("resolve generates expected BGL", async (t) => { - const path = input(); - const resolver = coreKit.resolve({ path }); - const b = board({ - inputs: { path }, - outputs: { resolved: resolver.unsafeOutput("resolved") }, - }); - const serialized = serialize(b); - t.deepEqual(serialized, { - edges: [ - { - from: "input-0", - in: "path", - out: "path", - to: "resolve-0", - }, - { - from: "resolve-0", - in: "resolved", - out: "resolved", - to: "output-0", - }, - ], - nodes: [ - { - id: "input-0", - type: "input", - configuration: { - schema: { - properties: { - path: { - type: "string", - }, - }, - required: ["path"], - type: "object", - }, - }, - }, - { - id: "output-0", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - resolved: { - type: [ - "array", - "boolean", - "null", - "number", - "object", - "string", - ], - }, - }, - required: ["resolved"], - }, - }, - }, - { - id: "resolve-0", - type: "resolve", - configuration: {}, - }, - ], - }); -}); diff --git a/packages/core-kit/tests/run-javascript.ts b/packages/core-kit/tests/run-javascript.ts deleted file mode 100644 index ea0745ea37c..00000000000 --- a/packages/core-kit/tests/run-javascript.ts +++ /dev/null @@ -1,647 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { NodeHandlerContext } from "@google-labs/breadboard"; - -import handler, { RunJavascriptOutputs } from "../src/nodes/run-javascript.js"; - -test("runJavascript runs code", async (t) => { - const runJavascript = handler.invoke; - const { result } = (await runJavascript( - { - code: "function run() { return 'hello world'; }", - }, - {} as NodeHandlerContext - )) as RunJavascriptOutputs; - t.is(result, "hello world"); -}); - -test("runJavascript correctly strips code", async (t) => { - const runJavascript = handler.invoke; - { - const { result } = (await runJavascript( - { - code: "```js\nfunction run() { return 'hello world'; }\n```", - }, - {} as NodeHandlerContext - )) as RunJavascriptOutputs; - t.is(result, "hello world"); - } - { - const { result } = (await runJavascript( - { - code: "```javascript\nfunction run() { return 'hello world'; }\n```", - }, - {} as NodeHandlerContext - )) as RunJavascriptOutputs; - t.is(result, "hello world"); - } -}); - -test("runJavascript runs code with specified function name", async (t) => { - const runJavascript = handler.invoke; - const { result } = (await runJavascript( - { - code: "function compute() { return 'hello world'; }", - name: "compute", - }, - {} as NodeHandlerContext - )) as RunJavascriptOutputs; - t.is(result, "hello world"); -}); - -test("runJavascript runs code with arguments", async (t) => { - const runJavascript = handler.invoke; - const { result } = (await runJavascript( - { - code: "function run({ what }) { return `hello ${what}`; }", - what: "world", - }, - {} as NodeHandlerContext - )) as RunJavascriptOutputs; - t.is(result, "hello world"); -}); - -test("runJavascript understands `raw` input", async (t) => { - const runJavascript = handler.invoke; - const result = (await runJavascript( - { - code: 'function compute() { return { hello: "world" }; }', - name: "compute", - raw: true, - }, - {} as NodeHandlerContext - )) as RunJavascriptOutputs; - t.deepEqual(result, { hello: "world" }); -}); - -test("raw=true with provided schemas", async (t) => { - const result = await handler.describe({ - raw: true, - inputSchema: { - type: "object", - properties: { foo: { type: "string" } }, - }, - outputSchema: { - type: "object", - properties: { bar: { type: "number" } }, - }, - }); - t.deepEqual(result, { - inputSchema: { - type: "object", - properties: { - code: { - type: "string", - title: "Code", - description: "The JavaScript code to run", - format: "javascript", - behavior: ["config", "code"], - }, - foo: { - type: "string", - }, - inputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "Input Schema", - description: "The schema of the input data, the function arguments.", - behavior: ["config", "ports-spec"], - }, - name: { - type: "string", - title: "Function Name", - description: - 'The name of the function to invoke in the supplied code. Default value is "run".', - default: "run", - behavior: ["config"], - }, - outputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "Output Schema", - description: - "The schema of the output data, the shape of the object of the function return value.", - behavior: ["config", "ports-spec"], - }, - raw: { - type: "boolean", - title: "Raw Output", - description: - "Whether or not to return use the result of execution as raw output (true) or as a port called `result` (false). Default is false.", - default: false, - behavior: ["config"], - }, - schema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "schema", - description: - "Deprecated! Please use inputSchema/outputSchema instead. The schema of the output data.", - behavior: ["config", "ports-spec", "deprecated"], - }, - }, - required: ["code"], - }, - outputSchema: { - type: "object", - properties: { - bar: { - type: "number", - }, - }, - required: [], - }, - }); -}); - -test("raw=true without provided schemas", async (t) => { - const result = await handler.describe({ raw: true }); - t.deepEqual(result, { - inputSchema: { - type: "object", - properties: { - code: { - type: "string", - title: "Code", - description: "The JavaScript code to run", - format: "javascript", - behavior: ["config", "code"], - }, - inputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "Input Schema", - description: "The schema of the input data, the function arguments.", - behavior: ["config", "ports-spec"], - }, - name: { - type: "string", - title: "Function Name", - description: - 'The name of the function to invoke in the supplied code. Default value is "run".', - default: "run", - behavior: ["config"], - }, - outputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "Output Schema", - description: - "The schema of the output data, the shape of the object of the function return value.", - behavior: ["config", "ports-spec"], - }, - raw: { - type: "boolean", - title: "Raw Output", - description: - "Whether or not to return use the result of execution as raw output (true) or as a port called `result` (false). Default is false.", - default: false, - behavior: ["config"], - }, - schema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "schema", - description: - "Deprecated! Please use inputSchema/outputSchema instead. The schema of the output data.", - behavior: ["config", "ports-spec", "deprecated"], - }, - }, - required: ["code"], - additionalProperties: true, - }, - outputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - }, - }); -}); - -test("raw=false with provided schemas", async (t) => { - const result = await handler.describe({ - raw: false, - inputSchema: { - type: "object", - properties: { foo: { type: "string" } }, - }, - outputSchema: { - type: "object", - properties: { result: { type: "number" } }, - }, - }); - t.deepEqual(result, { - inputSchema: { - type: "object", - properties: { - code: { - type: "string", - title: "Code", - description: "The JavaScript code to run", - format: "javascript", - behavior: ["config", "code"], - }, - foo: { - type: "string", - }, - inputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "Input Schema", - description: "The schema of the input data, the function arguments.", - behavior: ["config", "ports-spec"], - }, - name: { - type: "string", - title: "Function Name", - description: - 'The name of the function to invoke in the supplied code. Default value is "run".', - default: "run", - behavior: ["config"], - }, - outputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "Output Schema", - description: - "The schema of the output data, the shape of the object of the function return value.", - behavior: ["config", "ports-spec"], - }, - raw: { - type: "boolean", - title: "Raw Output", - description: - "Whether or not to return use the result of execution as raw output (true) or as a port called `result` (false). Default is false.", - default: false, - behavior: ["config"], - }, - schema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "schema", - description: - "Deprecated! Please use inputSchema/outputSchema instead. The schema of the output data.", - behavior: ["config", "ports-spec", "deprecated"], - }, - }, - required: ["code"], - }, - outputSchema: { - type: "object", - properties: { - result: { - description: "The result of running the JavaScript code", - title: "Result", - type: "number", - }, - }, - additionalProperties: false, - required: [], - }, - }); -}); - -test("raw=false without provided schemas", async (t) => { - const result = await handler.describe({ raw: false }); - t.deepEqual(result, { - inputSchema: { - type: "object", - properties: { - code: { - type: "string", - title: "Code", - description: "The JavaScript code to run", - format: "javascript", - behavior: ["config", "code"], - }, - inputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "Input Schema", - description: "The schema of the input data, the function arguments.", - behavior: ["config", "ports-spec"], - }, - name: { - type: "string", - title: "Function Name", - description: - 'The name of the function to invoke in the supplied code. Default value is "run".', - default: "run", - behavior: ["config"], - }, - outputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "Output Schema", - description: - "The schema of the output data, the shape of the object of the function return value.", - behavior: ["config", "ports-spec"], - }, - raw: { - type: "boolean", - title: "Raw Output", - description: - "Whether or not to return use the result of execution as raw output (true) or as a port called `result` (false). Default is false.", - default: false, - behavior: ["config"], - }, - schema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - title: "schema", - description: - "Deprecated! Please use inputSchema/outputSchema instead. The schema of the output data.", - behavior: ["config", "ports-spec", "deprecated"], - }, - }, - required: ["code"], - additionalProperties: true, - }, - outputSchema: { - type: "object", - properties: { - result: { - description: "The result of running the JavaScript code", - title: "Result", - type: ["array", "boolean", "null", "number", "object", "string"], - }, - }, - required: [], - additionalProperties: false, - }, - }); -}); - -test("real function computes as expected", async (t) => { - const code = function run(args: unknown) { - return { args }; - }.toString(); - - const result = await handler.invoke( - { - code, - raw: true, - }, - {} - ); - - t.deepEqual(result, { - args: {}, - }); -}); - -test("real function computes as expected with input", async (t) => { - const input = "Hello World"; - - const code = function run(args: unknown) { - return args; - }.toString(); - - const result = await handler.invoke( - { - input, - code, - raw: true, - }, - {} - ); - - t.deepEqual(result, { input }); -}); - -test("arrow function computes as expected", async (t) => { - const code = ((args: unknown) => { - return { args }; - }).toString(); - - const result = await handler.invoke( - { - code, - raw: true, - }, - {} - ); - - t.deepEqual(result, { - args: {}, - }); -}); - -test("arrow function computes as expected with input", async (t) => { - const input = "Hello World"; - - const code = ((args: unknown) => { - return args; - }).toString(); - - const result = await handler.invoke( - { - input, - code, - raw: true, - }, - {} - ); - - t.deepEqual(result, { input }); -}); - -test("anonymous function computes as expected", async (t) => { - const code = function (args: unknown) { - return { args }; - }.toString(); - - const result = await handler.invoke( - { - code, - raw: true, - }, - {} - ); - - t.deepEqual(result, { - args: {}, - }); -}); - -test("anonymous function computes as expected with input", async (t) => { - const input = "Hello World"; - - const code = function (args: unknown) { - return args; - }.toString(); - - const result = await handler.invoke( - { - input, - code, - raw: true, - }, - {} - ); - - t.deepEqual(result, { input }); -}); - -test("named function computes as expected", async (t) => { - const code = function run(args: unknown) { - return { args }; - }.toString(); - - const result = await handler.invoke( - { - code, - raw: true, - }, - {} - ); - - t.deepEqual(result, { - args: {}, - }); -}); - -test("named function computes as expected with input", async (t) => { - const input = "Hello World"; - - const code = function run(args: unknown) { - return args; - }.toString(); - - const result = await handler.invoke( - { - input, - code, - raw: true, - }, - {} - ); - - t.deepEqual(result, { input }); -}); - -test("anonymous function computes as expected when a name is provided", async (t) => { - const code = function (args: unknown) { - return { args }; - }.toString(); - - const result = await handler.invoke( - { - code, - name: "test", - raw: true, - }, - {} - ); - - t.deepEqual(result, { - args: {}, - }); -}); - -test("arrow function computes as expected when a name is provided", async (t) => { - const code = ((args: unknown) => { - return { args }; - }).toString(); - - const result = await handler.invoke( - { - code, - name: "test", - raw: true, - }, - {} - ); - - t.deepEqual(result, { - args: {}, - }); -}); - -test("named function computes as expected when a name is provided", async (t) => { - const code = function run(args: unknown) { - return { args }; - }.toString(); - - const result = await handler.invoke( - { - code, - name: "test", - raw: true, - }, - {} - ); - - t.deepEqual(result, { - args: {}, - }); -}); - -test("named function computes as expected when a name is provided and the function is anonymous", async (t) => { - function fn(args: unknown) { - return { args }; - } - - const result = await handler.invoke( - { - code: fn.toString(), - name: "test", - raw: true, - }, - {} - ); - - t.deepEqual(result, { - args: {}, - }); -}); - -test("named function computes as expected when a name is provided and the function is an arrow function", async (t) => { - const input = "Hello World"; - const fn = (args: unknown) => { - return { args }; - }; - - const result = await handler.invoke( - { - input, - code: fn.toString(), - name: "test", - raw: true, - }, - {} - ); - - t.deepEqual(result, { args: { input } }); -}); diff --git a/packages/core-kit/tests/secrets.ts b/packages/core-kit/tests/secrets.ts deleted file mode 100644 index 6666ee76fa1..00000000000 --- a/packages/core-kit/tests/secrets.ts +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { board, serialize } from "@breadboard-ai/build"; -import secrets, { secret } from "../src/nodes/secrets.js"; - -test("describer correctly responds to no inputs", async (t) => { - t.deepEqual(await secrets.describe(), { - inputSchema: { - type: "object", - properties: { - keys: { - title: "Secrets", - description: "The array of secrets to retrieve from the node.", - type: "array", - items: { - type: "string", - }, - behavior: ["config"], - }, - }, - required: ["keys"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: false, - }, - }); -}); - -test("describer correctly responds to inputs", async (t) => { - const inputs = { - keys: ["SECRET1", "SECRET2"], - }; - t.deepEqual(await secrets.describe(inputs), { - inputSchema: { - type: "object", - properties: { - keys: { - title: "Secrets", - description: "The array of secrets to retrieve from the node.", - type: "array", - items: { - type: "string", - }, - behavior: ["config"], - }, - }, - required: ["keys"], - additionalProperties: false, - }, - outputSchema: { - type: "object", - properties: { - SECRET1: { title: "SECRET1", type: "string" }, - SECRET2: { title: "SECRET2", type: "string" }, - }, - required: [], - additionalProperties: false, - }, - }); -}); - -test("secret utility serialization", async (t) => { - const foo = secret("SUPER"); - const bgl = serialize(board({ inputs: {}, outputs: { foo } })); - t.deepEqual(bgl, { - edges: [ - { - from: "SUPER-secret", - to: "output-0", - out: "SUPER", - in: "foo", - }, - ], - nodes: [ - { - id: "output-0", - type: "output", - configuration: { - schema: { - properties: { - foo: { - type: "string", - }, - }, - required: ["foo"], - type: "object", - }, - }, - }, - { - id: "SUPER-secret", - type: "secrets", - configuration: { - keys: ["SUPER"], - }, - }, - ], - }); -}); diff --git a/packages/data-store/.eslintrc b/packages/data-store/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/data-store/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/data-store/CHANGELOG.md b/packages/data-store/CHANGELOG.md deleted file mode 100644 index 50f3d08c322..00000000000 --- a/packages/data-store/CHANGELOG.md +++ /dev/null @@ -1,106 +0,0 @@ -# @breadboard-ai/data-store - -## 0.2.3 - -### Patch Changes - -- Updated dependencies [703f17d] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [4dadf16] -- Updated dependencies [8f9fddf] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [9797718] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [a039d2e] -- Updated dependencies [9783ba8] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [d7606d3] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] - - @google-labs/breadboard@0.27.0 - -## 0.2.2 - -### Patch Changes - -- Updated dependencies [7d46a63] - - @google-labs/breadboard@0.26.0 - -## 0.2.1 - -### Patch Changes - -- 534d67e: Teach Run Store & Data Store about LLM Content Array -- 262cefd: Skip metadata events in DataStore and RunStore -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @google-labs/breadboard@0.25.0 - -## 0.2.0 - -### Minor Changes - -- 3f8cdd1: Introduce run store - -### Patch Changes - -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [1dc645a] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [c04cff0] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - -## 0.1.0 - -### Minor Changes - -- 2b9ef5b: Rewrire Datastore usage -- 6ffa89c: Migrate to new data-store package - -### Patch Changes - -- fa93c3f: Add drop function to datastore -- 5ce1026: Attempt to add browser tests -- Updated dependencies [1e1be2a] -- Updated dependencies [2b094a3] -- Updated dependencies [fa93c3f] -- Updated dependencies [215bd15] -- Updated dependencies [2b9ef5b] -- Updated dependencies [a0852df] -- Updated dependencies [2312443] -- Updated dependencies [6ffa89c] - - @google-labs/breadboard@0.23.0 diff --git a/packages/data-store/package.json b/packages/data-store/package.json deleted file mode 100644 index 50931c7df30..00000000000 --- a/packages/data-store/package.json +++ /dev/null @@ -1,158 +0,0 @@ -{ - "name": "@breadboard-ai/data-store", - "version": "0.2.3", - "description": "A data store implementation to support Breadboard", - "main": "./dist/src/index.js", - "exports": { - ".": "./dist/src/index.js" - }, - "types": "dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "test": "wireit", - "test:ava": "wireit", - "test:browser": "wireit", - "build": "wireit", - "build:esbuild": "wireit", - "build:tsc": "wireit", - "lint": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "build:tsc" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "dependencies": [ - "../breadboard:build" - ], - "env": { - "FORCE_COLOR": "1" - }, - "files": [ - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/", - "!dist/**/*.min.js{,.map}" - ], - "clean": "if-file-deleted" - }, - "build:esbuild": { - "command": "esbuild tests/**/*.browser.test.ts --bundle --outdir=bundled --target=esnext --format=esm --external:node*", - "env": { - "FORCE_COLOR": "1" - }, - "files": [ - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "bundled" - ], - "clean": true - }, - "test": { - "dependencies": [ - "test:ava", - "test:browser" - ] - }, - "test:ava": { - "command": "ava", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - "tests/**/*.ts" - ], - "output": [] - }, - "test:browser": { - "command": "wtr bundled/**/*.browser.test.js", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:esbuild" - ], - "output": [] - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - } - }, - "repository": { - "directory": "packages/data-store", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src", - "dist/*.js", - "dist/*.js.map" - ], - "ava": { - "timeout": "30s", - "files": [ - "tests/**/*.nodejs.test.ts" - ], - "workerThreads": false, - "typescript": { - "rewritePaths": { - "./": "dist/" - }, - "compile": false - } - }, - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/data-store#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@esm-bundle/chai": "^4.3.4-fix.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/mocha": "^10.0.8", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "@web/dev-server-esbuild": "^1.0.2", - "@web/test-runner": "^0.19.0", - "ava": "^5.2.0", - "esbuild": "^0.24.0", - "typescript": "^5.6.2" - }, - "engines": { - "node": ">=20.14.0" - }, - "dependencies": { - "@google-labs/breadboard": "^0.27.0", - "idb": "^8.0.0" - } -} diff --git a/packages/data-store/src/index.ts b/packages/data-store/src/index.ts deleted file mode 100644 index e73a508531b..00000000000 --- a/packages/data-store/src/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - type RunStore, - type DataStore, - createDefaultDataStore, - createDefaultRunStore, -} from "@google-labs/breadboard"; -import { IDBRunStore } from "./run/idb-run-store.js"; - -// TODO: Allow for other data stores. -export function getDataStore(): DataStore { - return createDefaultDataStore(); -} - -export function getRunStore(forceInMemoryStore = false): RunStore { - if (forceInMemoryStore) { - console.log("[Breadboard Run Store] Using In-Memory Store (forced)"); - return createDefaultRunStore(); - } - - if ("indexedDB" in globalThis) { - console.log("[Breadboard Run Store] Using IDB Store"); - return new IDBRunStore(); - } - - console.log("[Breadboard Run Store] Using In-Memory Store"); - return createDefaultRunStore(); -} diff --git a/packages/data-store/src/run/idb-run-store.ts b/packages/data-store/src/run/idb-run-store.ts deleted file mode 100644 index 2df16fd9b66..00000000000 --- a/packages/data-store/src/run/idb-run-store.ts +++ /dev/null @@ -1,286 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as idb from "idb"; -import { HarnessRunResult } from "@google-labs/breadboard/harness"; -import { - isLLMContent, - isLLMContentArray, - isMetadataEntry, - isStoredData, - LLMContent, - RunStore, - RunTimestamp, - RunURL, - toInlineDataPart, -} from "@google-labs/breadboard"; - -const RUN_LISTING_DB = "run-listing"; -const RUN_LISTING_VERSION = 1; - -interface RunListing extends idb.DBSchema { - urls: { - key: "url"; - value: { - url: string; - }; - }; -} - -export class IDBRunStore implements RunStore { - #writers: Map> = - new Map(); - - #urlToDbName(url: string) { - return `run-${url}`; - } - - constructor() { - // Remove the deprecated 'runs' database if it exists. - try { - idb.deleteDB("runs"); - } catch (err) { - // Best effort - don't throw if there are any issues. - } - } - - /** - * Starts tracking a run. - * - * @param storeId The ID of the store to create. - * @param releaseGroupIds The IDs of any old stores to be released. - * @returns The store ID used. - */ - async start(url: RunURL): Promise { - // 1. Store the URLs that we've seen (necessary to support the truncation - // and drop calls). - const runListing = await idb.openDB( - RUN_LISTING_DB, - RUN_LISTING_VERSION, - { - upgrade(db) { - db.createObjectStore("urls", { keyPath: "url" }); - }, - } - ); - await runListing.put("urls", { url }); - runListing.close(); - - // 2. Create a database and object store for this particular run. - const dbName = this.#urlToDbName(url); - const timestamp = Date.now(); - const timestampKey = timestamp.toString(); - const dbVersion = await idb.openDB(dbName); - const nextVersion = dbVersion.version + 1; - dbVersion.close(); - - // 3. Set up a stream to write to the new database. - let db: idb.IDBPDatabase; - const stream = new WritableStream({ - async start() { - db = await idb.openDB(dbName, nextVersion, { - blocked(currentVersion, blockedVersion, event) { - console.warn( - `IDB Store blocked version ${blockedVersion} by version ${currentVersion}`, - event - ); - }, - - upgrade(db) { - db.createObjectStore(timestampKey, { - keyPath: "id", - autoIncrement: true, - }); - }, - }); - - db.close(); - }, - async write(chunk: HarnessRunResult) { - try { - const result = JSON.parse(JSON.stringify(chunk)) as HarnessRunResult; - - // Before storing any inputs, check if they are using StoredDataParts. - // If so inflate them back to inlineData before storage. - if (result.type === "nodeend" && result.data.node.type === "input") { - for (const output of Object.values(result.data.outputs)) { - if (!isLLMContent(output) && !isLLMContentArray(output)) { - continue; - } - - const outputs: LLMContent[] = isLLMContent(output) - ? [output] - : output; - for (const output of outputs) { - if (isMetadataEntry(output)) { - continue; - } - - for (let i = 0; i < output.parts.length; i++) { - const part = output.parts[i]; - if (!isStoredData(part)) { - continue; - } - - output.parts[i] = await toInlineDataPart(part); - } - } - } - } - - db = await idb.openDB(dbName); - const tx = db.transaction(timestampKey, "readwrite"); - await Promise.all([tx.store.add(result), tx.done]); - } catch (err) { - console.warn( - `Unable to write to storage (URL: ${url}, Timestamp: ${timestampKey})`, - chunk - ); - console.warn(err); - if (this.abort) { - this.abort(); - } - } finally { - db.close(); - } - }, - abort() { - db.close(); - }, - close() { - db.close(); - }, - }); - - // 4. Store the writer and return the timestamp. - let store = this.#writers.get(url); - if (!store) { - store = new Map< - RunTimestamp, - WritableStreamDefaultWriter - >(); - this.#writers.set(url, store); - } - - if (store.has(timestamp)) { - throw new Error("Already writing a stream - please stop it first"); - } - - store.set(timestamp, stream.getWriter()); - return timestamp; - } - - async write( - url: RunURL, - timestamp: RunTimestamp, - result: HarnessRunResult - ): Promise { - const store = this.#writers.get(url); - if (!store) { - throw new Error("No active stream - please start one before writing"); - } - - const writer = store.get(timestamp); - if (!writer) { - throw new Error("No active stream - please start one before writing"); - } - - await writer.ready; - writer.write(result); - } - - async stop(url: RunURL, timestamp: RunTimestamp) { - const store = this.#writers.get(url); - if (!store) { - throw new Error("No active stream - please start one before writing"); - } - - const writer = store.get(timestamp); - if (!writer) { - throw new Error("No active stream - please start one before writing"); - } - - await writer.ready; - writer.close(); - store.delete(timestamp); - } - - async abort(url: RunURL, timestamp: RunTimestamp) { - const store = this.#writers.get(url); - if (!store) { - throw new Error("No active stream - please start one before writing"); - } - - const writer = store.get(timestamp); - if (!writer) { - throw new Error("No active stream - please start one before writing"); - } - - await writer.ready; - writer.abort(); - store.delete(timestamp); - } - - async drop(url?: RunURL) { - if (url) { - await idb.deleteDB(this.#urlToDbName(url)); - return; - } - - const runListing = await idb.openDB(RUN_LISTING_DB); - if (runListing.objectStoreNames.contains("urls")) { - const urls = await runListing.getAll("urls"); - for (const item of urls) { - await idb.deleteDB(this.#urlToDbName(item.url)); - } - } - - runListing.close(); - await idb.deleteDB(RUN_LISTING_DB); - } - - async truncate(url: RunURL, limit: number): Promise { - const dbName = this.#urlToDbName(url); - const db = await idb.openDB(dbName); - const nextVersion = db.version + 1; - const storesToRemove = [...db.objectStoreNames] - .sort((a, b) => { - return Number.parseInt(b) - Number.parseInt(a); - }) - .slice(limit); - db.close(); - - // Now re-open the database with a new version and use that operation to - // delete the stores that are no longer needed. - const truncateDb = await idb.openDB(this.#urlToDbName(url), nextVersion, { - upgrade(db) { - for (const store of storesToRemove) { - db.deleteObjectStore(store); - } - }, - }); - truncateDb.close(); - } - - async getStoredRuns( - url: RunURL - ): Promise> { - const dbName = this.#urlToDbName(url); - const db = await idb.openDB(dbName); - const runs = await Promise.all( - [...db.objectStoreNames].map(async (timestamp) => { - const events = (await db.getAll(timestamp)) as HarnessRunResult[]; - return [Number.parseInt(timestamp), events] as [ - RunTimestamp, - HarnessRunResult[], - ]; - }) - ); - db.close(); - - return new Map(runs); - } -} diff --git a/packages/data-store/tests/index.test.ts b/packages/data-store/tests/index.test.ts deleted file mode 100644 index 68d31d5e9dc..00000000000 --- a/packages/data-store/tests/index.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { getDataStore } from "../src/index.js"; - -test("getStore can find a store", async (t) => { - const store = getDataStore(); - t.truthy(store, "Unable to find store"); -}); diff --git a/packages/data-store/tests/run/idb-run-store.browser.test.ts b/packages/data-store/tests/run/idb-run-store.browser.test.ts deleted file mode 100644 index dec4aa24d95..00000000000 --- a/packages/data-store/tests/run/idb-run-store.browser.test.ts +++ /dev/null @@ -1,272 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { expect } from "@esm-bundle/chai"; -import { IDBRunStore } from "../../src/run/idb-run-store.js"; - -import { results as simpleRunResults } from "./simple-run.js"; -import { results as inlineDataRunResults } from "./inline-data-run.js"; -import { results as inlineDataArrayRunResults } from "./inline-data-run-array.js"; -import { - isInlineData, - isLLMContent, - isLLMContentArray, - toStoredDataPart, -} from "@google-labs/breadboard"; -import { HarnessRunResult } from "@google-labs/breadboard/harness"; - -const url = "http://www.example.com"; - -const delay = (ms: number) => new Promise((r) => setTimeout(r, ms)); - -const inputResult: HarnessRunResult = { - type: "nodeend", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - }, - inputs: {}, - path: [], - timestamp: 10, - outputs: { - content: { - role: "user", - parts: [ - { - inlineData: { - data: "aabbcc", - mimeType: "text/plain", - }, - }, - ], - }, - }, - }, - async reply() {}, -}; - -function copyResult(result: HarnessRunResult): HarnessRunResult { - // We can't use structuredClone because of the async function, so we fall back - // to using parse/stringify to make a copy. - return JSON.parse(JSON.stringify(result)); -} - -before(async () => { - const store = new IDBRunStore(); - await store.drop(); -}); - -it("IDBRunStore stores run events", async () => { - const runStore = new IDBRunStore(); - const url = "http://www.example.com"; - const timestamp = await runStore.start(url); - - for (const result of simpleRunResults) { - await runStore.write(url, timestamp, result); - } - - await runStore.stop(url, timestamp); - const runs = await runStore.getStoredRuns(url); - - expect(runs.size).to.equal(1); - expect([...runs.values()][0].length).to.equal(8); - - await runStore.drop(); -}); - -it("IDBRunStore creates multiple stores per URL", async () => { - const runStore = new IDBRunStore(); - - const runTimestamp = await runStore.start(url); - await runStore.stop(url, runTimestamp); - - // Wait 10ms so that the timestamps of the two runs don't clash. - await delay(10); - - const runTimestamp2 = await runStore.start(url); - await runStore.stop(url, runTimestamp2); - - const runs = await runStore.getStoredRuns(url); - expect(runs.size).to.equal(2); - - await runStore.drop(); -}); - -it("IDBRunStore writes data", async () => { - const runStore = new IDBRunStore(); - const result = copyResult(inputResult); - const runTimestamp = await runStore.start(url); - await runStore.write(url, runTimestamp, result); - await runStore.stop(url, runTimestamp); - const runs = await runStore.getStoredRuns(url); - - expect(runs.size).to.equal(1); - expect(runs.get(runTimestamp)![0].type).to.deep.equal(result.type); - expect(runs.get(runTimestamp)![0].data).to.deep.equal(result.data); - await runStore.drop(); -}); - -it("IDBRunStore drops data", async () => { - const runStore = new IDBRunStore(); - const result = copyResult(inputResult); - const runTimestamp = await runStore.start(url); - await runStore.write(url, runTimestamp, result); - await runStore.stop(url, runTimestamp); - await runStore.drop(); - const runs = await runStore.getStoredRuns(url); - expect(runs.size).to.equal(0); -}); - -it("IDBRunStore truncates data", async () => { - const runStore = new IDBRunStore(); - const result = copyResult(inputResult); - - const runTimestamp = await runStore.start(url); - await runStore.write(url, runTimestamp, result); - await runStore.stop(url, runTimestamp); - - // Wait 10ms so that the timestamps of the two runs don't clash. - await delay(10); - - const runTimestamp2 = await runStore.start(url); - await runStore.write(url, runTimestamp2, result); - await runStore.stop(url, runTimestamp2); - - await runStore.truncate(url, 1); - const runs = await runStore.getStoredRuns(url); - expect(runs.size).to.equal(1); - expect(runs.get(runTimestamp2)).to.be.ok; - - await runStore.drop(); -}); - -it("IDBRunStore replaces storedData with inlineData when writing (LLM Content)", async () => { - // Step 1. Write the data in, converting inlineData parts to storedDataParts - // before they get written in. - const runStore = new IDBRunStore(); - const timestamp = await runStore.start(url); - - for (const result of inlineDataRunResults) { - if (result.type === "nodeend" && result.data.node.type === "input") { - for (const output of Object.values(result.data.outputs)) { - if (!isLLMContent(output)) { - continue; - } - - for (let i = 0; i < output.parts.length; i++) { - const part = output.parts[i]; - if (!isInlineData(part)) { - continue; - } - - output.parts[i] = await toStoredDataPart(part); - } - } - } - - await runStore.write(url, timestamp, result); - } - - await runStore.stop(url, timestamp); - - // Step 2. Get the run. - const run = await runStore.getStoredRuns(url); - const runValues = [...run.values()]; - - expect(run.size).to.equal(1); - expect(runValues[0].length).to.equal(8); - expect(runValues[0][3].type).to.equal("nodeend"); - - // Step 3. Assert we have an inlineData object. - const nodeToInspect = runValues[0][3]; - if ( - nodeToInspect.type === "nodeend" && - nodeToInspect.data.node.type === "input" - ) { - const outputs = Object.values(nodeToInspect.data.outputs); - expect(outputs.length).to.equal(1); - for (const output of outputs) { - expect(isLLMContent(output), "Output is not LLM Content").to.be.ok; - - if (isLLMContent(output)) { - for (const part of output.parts) { - expect(isInlineData(part), "Part is not inlineData").to.be.ok; - } - } - } - } else { - expect.fail("Unexpected node type"); - } - - await runStore.drop(); -}); - -it("IDBRunStore replaces storedData with inlineData when writing (LLM Content Array)", async () => { - // Step 1. Write the data in, converting inlineData parts to storedDataParts - // before they get written in. - const runStore = new IDBRunStore(); - const timestamp = await runStore.start(url); - - for (const result of inlineDataArrayRunResults) { - if (result.type === "nodeend" && result.data.node.type === "input") { - for (const output of Object.values(result.data.outputs)) { - if (!isLLMContentArray(output)) { - continue; - } - - for (const entry of output) { - for (let i = 0; i < entry.parts.length; i++) { - const part = entry.parts[i]; - if (!isInlineData(part)) { - continue; - } - - entry.parts[i] = await toStoredDataPart(part); - } - } - } - } - - await runStore.write(url, timestamp, result); - } - - await runStore.stop(url, timestamp); - - // Step 2. Get the run. - const run = await runStore.getStoredRuns(url); - const runValues = [...run.values()]; - - expect(run.size).to.equal(1); - expect(runValues[0].length).to.equal(9); - expect(runValues[0][3].type).to.equal("nodeend"); - - // Step 3. Assert we have an inlineData object. - const nodeToInspect = runValues[0][3]; - if ( - nodeToInspect.type === "nodeend" && - nodeToInspect.data.node.type === "input" - ) { - const outputs = Object.values(nodeToInspect.data.outputs); - expect(outputs.length).to.equal(1); - for (const output of outputs) { - expect(isLLMContentArray(output), "Output is not LLM Content Array").to.be - .ok; - - if (isLLMContentArray(output)) { - for (const entry of output) { - for (const part of entry.parts) { - expect(isInlineData(part), "Part is not inlineData").to.be.ok; - } - } - } - } - } else { - expect.fail("Unexpected node type"); - } - - await runStore.drop(); -}); diff --git a/packages/data-store/tests/run/inline-data-run-array.ts b/packages/data-store/tests/run/inline-data-run-array.ts deleted file mode 100644 index bc471c73ef7..00000000000 --- a/packages/data-store/tests/run/inline-data-run-array.ts +++ /dev/null @@ -1,514 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "@google-labs/breadboard/harness"; - -export const results: HarnessRunResult[] = [ - { - type: "graphstart", - data: { - graph: { - title: "Blank board", - description: - "A blank board. Use it as a starting point for your creations.", - version: "0.0.1", - nodes: [ - { - type: "input", - id: "input", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 0, - y: 0, - collapsed: true, - }, - }, - }, - { - type: "output", - id: "output", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 173, - y: 0, - collapsed: true, - }, - }, - }, - ], - edges: [ - { - from: "input", - out: "context", - to: "output", - in: "context", - }, - ], - url: "idb://default/blank-board.bgl.json", - }, - path: [], - timestamp: 68300.29999999702, - }, - async reply() {}, - }, - { - type: "nodestart", - data: { - node: { - type: "input", - id: "input", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 0, - y: 0, - collapsed: true, - }, - }, - }, - inputs: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - path: [1], - timestamp: 68356.60000000149, - }, - async reply() {}, - }, - { - type: "input", - data: { - node: { - type: "input", - id: "input", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 0, - y: 0, - collapsed: true, - }, - }, - }, - inputArguments: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - path: [1], - bubbled: false, - timestamp: 68364.20000000298, - }, - async reply() {}, - }, - { - type: "nodeend", - data: { - node: { - type: "input", - id: "input", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 0, - y: 0, - collapsed: true, - }, - }, - }, - inputs: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: '[{"role":"user","parts":[{"text":""}]}]', - }, - }, - type: "object", - required: [], - }, - }, - outputs: { - context: [ - { - role: "user", - parts: [ - { - inlineData: { - mimeType: "image/png", - data: "iVBORw0KGgoAAAANSUhEUgAAAUAAAADwCAYAAABxLb1rAAAAAXNSR0IArs4c6QAAD+hJREFUeF7t3UuIHNXbB+AzcYxBIYhoUHChEEQQvIyJcZF4iUQFNwrGpWJcutGNiAq6ERQR40ZQCChiiOjCRYwXjKIJmqhJMOBSsxbBeIMRdJKP0x89/5rJJJnqfrumz5ynIWBM1VvnPO+Z31R3VXdPnDx58mTyIECAQIUCEwKwwq6bMgECPQEBaCEQIFCtgACstvUmToCAALQGCBCoVkAAVtt6EydAQABaAwQIVCsgAKttvYkTICAArQECBKoVEIDVtt7ECRAQgNYAAQLVCgjAaltv4gQICEBrgACBagUEYLWtN3ECBASgNUCAQLUCArDa1ps4AQIC0BogQKBaAQFYbetNnAABAWgNECBQrYAArLb1Jk6AgAC0BggQqFZAAFbbehMnQEAAWgMECFQrIACrbb2JEyAgAK0BAgSqFRCA1bbexAkQEIDWAAEC1QoIwGpbb+IECAhAa4AAgWoFBGC1rTdxAgQEoDVAgEC1AgKw2tabOAECAtAaIECgWgEBWG3rTZwAAQFoDRAgUK2AAKy29SZOgIAAtAYIEKhWQABW23oTJ0BAAFoDBAhUKyAAq229iRMgIACtAQIEqhUQgNW23sQJEBCA1gABAtUKCMBqW2/iBAgIQGuAAIFqBQRgta03cQIEBKA1QIBAtQICsNrWmzgBAgLQGiBAoFoBAVht602cAAEBaA0QIFCtgACstvUmToCAALQGCBCoVkAAVtt6EydAQABaAwQIVCsgAKttvYkTICAArQECBKoVEIDVtt7ECRAQgNYAAQLVCgjAaltv4gQICEBrgACBagUEYLWtN3ECBASgNUCAQLUCArDa1ps4AQICsMA1cOONN/ZGPTExMTv6kydPphMnTqQjR44UOCNDJrA0AgJwadwHPurU1FRasWLFgvvnEDx06NDAte1IoDYBAVhQx99+++20ffv2OWd+/eHn8Mt/Dh8+XNCMDJXA0goIwKX1b3X05tlfDrtHH300bdu2rVUNGxMg8D8BAVjIali3bt2ckXq6W0jjDHOsBQTgWLfnf4PLFz76Fz1y+H3xxRdp9erVSz76/llpHtPZHnmba6+9Nr355ptn29S/E+hEQAB2wjzcQeaH39VXX53eeeed4YoG7H3DDTekc845p3UlZ6+tyewwIgEBOCLYqLKbN29Of/zxx+zZX77VZVwudNx5553pt99+G3iq33///cD72pFAhIAAjFAcUY3bbrst/f3337PV85lTPvPLZ4Dj8sgBffz48TnDyU/Vm3/ybTv9+xT7G+a/X3/99WnHjh3jMhXjqFBAAI5x0+c/9d2yZUt64YUXxnjEZx5aPlvMc2i+lnnw4ME0OTlZ7JwMvGwBATjG/Vu/fn3vzCk/nn/++XTXXXeN8WgXN7Tnnnsu7d69e3bjyy+/PH3wwQeL29lWBIIFBGAwaGS5HBaffPJJL/jyfy+Xx6ZNm9L09PTsdLwWuFw6W948BGB5PSt+xPmiTn7tsP9U+OOPP04XX3xx8fMygfIEBGB5PVsWI37llVfSzp0705VXXpnyW/zOO++8ZTEvkyhLQACW1S+jJUAgUEAABmIqRYBAWQICsKx+GS0BAoECAjAQUykCBMoSEIBl9ctoCRAIFBCAgZhKESBQloAALKtfRkuAQKCAAAzEVIoAgbIEBGBZ/TJaAgQCBQRgIKZSBAiUJSAAy+qX0RIgECggAAMxlSJAoCwBAVhWv4yWAIFAAQEYiDkupZ544ol0xx13LIsPUB0XU+NYngICcJn1dcOGDWlmZqb3SdK33HJLyh875UGAwMICAnCZrYzm94jkqfm05WXWYNMJFRCAoZxLX6z/ReV5JPk7e/OXDnkQIOAMsIo10AzAlStXpq+//nok8163bl2v7saNG9P27dtHcgxFCYxawBngqIU7rt8MwFWrVqX9+/eHj2Dr1q3p2LFjvbr5tcZDhw6FH0NBAl0ICMAulDs8RvM1wAsuuCB9+eWX4UdvfmG7AAznVbBDAQHYIXYXh2oG4OrVq9Pnn38efth77rkn/fLLL84Aw2UV7FpAAHYtPuLj9V+by4dZs2ZN2rNnT/gRH3jggfTzzz8LwHBZBbsWEIBdi4/4eDfddFM6ceJE7yhXXHFFev/998OP+NBDD6Uff/xRAIbLKti1gADsWnzEx9u0aVOanp7uHSWH4WuvvRZ+xMcffzzt27dvtq57DcOJFexIQAB2BN3VYbZt25aOHj3aO9zTTz+d7rvvvvBDv/jii+m9997r1Z2cnEwHDhwIP4aCBLoQEIBdKHd4jJ9++im9/PLL6aKLLkrPPvtsOvfcc8OP/umnn6annnqqV/eSSy5JH330UfgxFCTQhYAA7EJ5mR3j33//Tffee2/6/fff02OPPZbyfYEeBEoUEIAlds2YCRAIERCAIYyKECBQooAALLFrxkyAQIiAAAxhVIQAgRIFBGDLruW3mnnzf0s0mxMYUwEB2KIx/ffZ+gCAFmg2JTDGAgKwRXOaHzSwY8eOdN1117XY26YECIybgABs0ZHmBw3kt5jlt5p5ECBQroAAbNG75hngVVddlXbu3Nlib5sSIDBuAgKwRUeaZ4Cvv/56yoHoQYBAuQICsEXvmmeAa9euTbt27Wqxt00JEBg3AQHYoiNdfNx8i+HYlACBIQUEYAvAZgD6yskWcDYlMKYCArBFY5oBODMzk44cOdJib5sSIDBuAgKwRUeaAZh380nILfCCNt27d2969dVX04MPPpjuv//+oKrK1CogAFt0vhmA3g3SAi5w0/6V+OyfP4g1f/GTB4FBBQRgC7n169f3vgg8PwRgC7jATZu3IrkXMxC20lICsEXjb7755vTff//N7rFq1aq0f//+FhVsOqzA/B54GWJY0br3F4At++9pcEuw4M0feeSR9MMPP8yehT/zzDMj+eKn4GErN6YCArBlY6amptKKFSt6e+Xv3z18+HDLCjYfVqD5Syj34ttvvx22pP0rFRCALRvvSnBLsBFs3vzyd6/FjgC4opICsGWz83uA33jjjTQxMTH7NMwHpLZEHHLz5uuAAnBIzMp3F4ADLABngQOgBe7ianwgZuWlBOAAC6D5A5h3dyVyAMQhdmneCuMMcAhIuyYBOMAiaP4A9ncXggNADriLK/EDwtntFAEBOOCi8DR4QLiA3eb/AvLLJwC10hICcMDGzz8L+fDDD9Oll146YDW7tREQgG20bHsmAQE44Po4duxY2rp165y9nYkMiNlyN68BtgSz+WkFBOAQi8MP4hB4Q+zKfQg8u84REIBDLIj5V4O9K2EIzEXu+vDDD6ejR4/O3oeZX3bYvXv3Ive2GYG5AgJwyBXhiuSQgC139/pfSzCbn1FAAA65QNwSMyRgi93nn3G7B7AFnk0XFBCAAQtj/llg/pAEH5cfADuvhFuP4k1rrygAA1bA3XffnX799dc57w/+5ptv0sqVKwOqK5EF5p9p+1Iq6yJCQABGKC7wA+rpWRBsSr0voO9/+ES/qluO4nxrriQAA7s//ywl/9B+9913gUeoq9RCwecXS11rYNSzFYCBwtPT02njxo1zzlbcGjMYsPAbzM1e7QQEYDuvs26dzwLzWYqnbGelWnCDJ598Mn322Wen/Jszv8E87XVmAQE4ghWyYcOG3pcnNT809fzzz0/79u0bwdGWT8mFbinKwZf/+OqB5dPncZqJABxRNxZ6Crdr1660du3aER2x3LK33357+vPPP085a84zuuaaa9Jbb71V7uSMfKwFBOAI2+Pq5ZlxFzrjy3vkM7782qkLSCNcnEr3BATgiBeCK8OnAje/1Ggh/jVr1qQ9e/aMuDPKExCAI18DL730Unr33XdPOU6N97HNfytbE6V/4ahGl5EvQgc4rYAzwA4Wx0IXRSYnJ9PBgwc7OPrSHmLLli3p+PHjZxyEK7xL26Oajy4AO+r+/Kd9+Yc+P5brV2qe7nagPrerux0tPIc5o4AA7HCBTE1N9V7cb4bAcgrB/uudC90HmefZ///5lqCvvvqqQ3mHIrCwgADseGUsdAGg5KeAmzdvTn/99VfKn4Az/+bvZtDnf/P6XseLzeHOKiAAz0oUv8FCt8c0z5DGOSjyWWwOs/yn/zT+TMG3nM5w41eCikstIACXqAPNIJk/hPlPIfMFkwMHDizJSPvj7B/8dGHXHFzJZ7RLguygSyYgAJeM/v8PfLqbgU83rNO9vhY5jUGOkfe58MIL0969eyOHohaBkQoIwJHyLr54fm1wZmamt8NizrIWXzl+y35AOtOLt1WxWwEB2K33oo+WXyfMV4zzxYWlDMXm2WD+78suu8y3sC26izYcdwEBOO4daozv1ltvTf/880/v4kM/GPvh2Pz7oFPqX9zoX9F1hjeopP1KERCApXTKOAkQCBcQgOGkChIgUIqAACylU8ZJgEC4gAAMJ1WQAIFSBARgKZ0yTgIEwgUEYDipggQIlCIgAEvplHESIBAuIADDSRUkQKAUAQFYSqeMkwCBcAEBGE6qIAECpQgIwFI6ZZwECIQLCMBwUgUJEChFQACW0injJEAgXEAAhpMqSIBAKQICsJROGScBAuECAjCcVEECBEoREICldMo4CRAIFxCA4aQKEiBQioAALKVTxkmAQLiAAAwnVZAAgVIEBGApnTJOAgTCBQRgOKmCBAiUIiAAS+mUcRIgEC4gAMNJFSRAoBQBAVhKp4yTAIFwAQEYTqogAQKlCAjAUjplnAQIhAsIwHBSBQkQKEVAAJbSKeMkQCBcQACGkypIgEApAgKwlE4ZJwEC4QICMJxUQQIEShEQgKV0yjgJEAgXEIDhpAoSIFCKgAAspVPGSYBAuIAADCdVkACBUgQEYCmdMk4CBMIFBGA4qYIECJQiIABL6ZRxEiAQLiAAw0kVJECgFAEBWEqnjJMAgXABARhOqiABAqUICMBSOmWcBAiECwjAcFIFCRAoRUAAltIp4yRAIFxAAIaTKkiAQCkCArCUThknAQLhAgIwnFRBAgRKERCApXTKOAkQCBcQgOGkChIgUIqAACylU8ZJgEC4gAAMJ1WQAIFSBARgKZ0yTgIEwgUEYDipggQIlCIgAEvplHESIBAuIADDSRUkQKAUAQFYSqeMkwCBcAEBGE6qIAECpQgIwFI6ZZwECIQLCMBwUgUJEChFQACW0injJEAgXEAAhpMqSIBAKQICsJROGScBAuECAjCcVEECBEoREICldMo4CRAIFxCA4aQKEiBQioAALKVTxkmAQLiAAAwnVZAAgVIEBGApnTJOAgTCBQRgOKmCBAiUIiAAS+mUcRIgEC4gAMNJFSRAoBQBAVhKp4yTAIFwAQEYTqogAQKlCAjAUjplnAQIhAsIwHBSBQkQKEVAAJbSKeMkQCBcQACGkypIgEApAgKwlE4ZJwEC4QICMJxUQQIEShEQgKV0yjgJEAgXEIDhpAoSIFCKwP8B5wTti5uv54YAAAAASUVORK5CYII=", - }, - }, - ], - }, - ], - }, - path: [1], - timestamp: 70183.20000000298, - }, - async reply() {}, - }, - { - type: "nodestart", - data: { - node: { - type: "output", - id: "output", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 173, - y: 0, - collapsed: true, - }, - }, - }, - inputs: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - context: [ - { - role: "user", - parts: [ - { - storedData: { - handle: - "blob:http://localhost:5173/f28de4b7-0ace-4d76-912e-70ee79048053", - mimeType: "image/png", - }, - }, - ], - }, - ], - }, - path: [2], - timestamp: 70193.29999999702, - }, - async reply() {}, - }, - { - type: "output", - data: { - node: { - type: "output", - id: "output", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 173, - y: 0, - collapsed: true, - }, - }, - }, - outputs: { - context: [ - { - role: "user", - parts: [ - { - storedData: { - handle: - "blob:http://localhost:5173/f28de4b7-0ace-4d76-912e-70ee79048053", - mimeType: "image/png", - }, - }, - ], - }, - ], - }, - path: [2], - timestamp: 70203.60000000149, - bubbled: false, - }, - async reply() {}, - }, - { - type: "nodeend", - data: { - node: { - type: "output", - id: "output", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 173, - y: 0, - collapsed: true, - }, - }, - }, - inputs: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - context: [ - { - role: "user", - parts: [ - { - storedData: { - handle: - "blob:http://localhost:5173/f28de4b7-0ace-4d76-912e-70ee79048053", - mimeType: "image/png", - }, - }, - ], - }, - ], - }, - outputs: {}, - path: [2], - timestamp: 70207.89999999851, - }, - async reply() {}, - }, - { - type: "graphend", - data: { - path: [], - timestamp: 70210.39999999851, - }, - async reply() {}, - }, - { - type: "end", - data: { - timestamp: 70213.20000000298, - last: { - node: { - type: "output", - id: "output", - configuration: { - schema: { - properties: { - context: { - type: "array", - title: "Context", - examples: [], - items: { - type: "object", - behavior: ["llm-content"], - }, - default: "null", - }, - }, - type: "object", - required: [], - }, - }, - metadata: { - visual: { - x: 173, - y: 0, - collapsed: true, - }, - }, - }, - missing: [], - }, - }, - async reply() {}, - }, -]; diff --git a/packages/data-store/tests/run/inline-data-run.ts b/packages/data-store/tests/run/inline-data-run.ts deleted file mode 100644 index d1a47ab6979..00000000000 --- a/packages/data-store/tests/run/inline-data-run.ts +++ /dev/null @@ -1,362 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "@google-labs/breadboard/harness"; - -export const results: HarnessRunResult[] = [ - { - type: "graphstart", - data: { - graph: { - url: "idb://default/blank-board.bgl.json", - title: "Blank board", - description: - "A blank board. Use it as a starting point for your creations.", - $schema: - "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.5.1/packages/schema/breadboard.schema.json", - version: "0.0.1", - edges: [ - { - from: "input-45dd0a3d", - to: "output-b8d7ce06", - out: "content", - in: "content", - }, - ], - nodes: [ - { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - ], - kits: [], - }, - path: [], - timestamp: 2156.099999964237, - }, - async reply() {}, - }, - { - type: "nodestart", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - path: [1], - timestamp: 2167.2999999523163, - }, - async reply() {}, - }, - { - type: "input", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputArguments: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - path: [1], - bubbled: false, - timestamp: 2172.899999976158, - }, - async reply() {}, - }, - { - type: "nodeend", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - outputs: { - content: { - role: "user", - parts: [ - { - inlineData: { - data: "iVBORw0KGgoAAAANSUhEUgAAAPQAAAC3CAYAAAAl43M8AAAAAXNSR0IArs4c6QAACb1JREFUeF7t3buO1EwTgOGGRURIcAEEcAecxSkjJOAQEBBwA0gQkAESISIn5wKAjBCEkBDitAtCIiQDcQmc2U+9+md/M8ww9tgu7/Y+lhBasLtcb9U77mnveDYtLy8vJxsCCBRBYBOhi6ijJBBYIUBojYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVMxpqezbty9t3rw5LS8vr+yS/379+vXKv9nKIkDoNVDP27dvpzt37qzKloV78+ZNJ2c2knnSYNu3b0+PHj3qJI5B1gYBQq+BOuzfvz9t2rTpjzPJUi8uLrY+u38J/fv377S0tNQ6hgHWDgFCD1yLAwcOTDyDLmTLMucXitGLxWjKXf25ixeNgREKXyFA6IHbYZrQXVyhx6/8CwsL6efPn3/MBvJ7aVs5BAg9cC0nTbfzKXVxhZ42djVlQg/cAB2HJ3THQJsON+0KvWvXrnTv3r2mw/2x//iUu/qfXcwAWp2cg3shQOhesNYf9PDhwyvT4NGWRct/ulqs2rt378rtqeqiWx7/x48f6d27d/VP1J7rggChBy7T58+f08mTJ1cXr379+tXZLauBUxN+AAKEHgC6kAj0RYDQfZE1LgIDECD0ANCFRKAvAoTui6xxERiAAKEHgC4kAn0RIHRfZI2LwAAECD0AdCER6IsAofsia1wEBiBA6AGgC4lAXwQI3RdZ4yIwAAFCDwBdSAT6IkDoGWTPnTuXPnz4sLJX/j3rt2/f9lUL4yLQmgChZyCsPsLHRw5b95sBeiZA6BmAqw8JIHTP3Wj41gQI7QrduomaDPDx48e0c+fOJofYtwEBQhO6Qbu02/XKlSvpyZMnaevWrenZs2ftBnP0RAKEbiB03tUzuOY3qfq4pevXr6fTp0/PP5gjCT1PD1gUm4fa5GOq6xH50Uv5CwZs3RJwhbYo1m1H/WO0qtC7d+9Od+/eDYu9UQIRmtBhvV6dcp85cyZdu3YtLPZGCUToGZW+ceNGevDgwepTMz3Ebz41Tp06lT59+rR6sLWI+TjOOorQswillNyLrgHJTKc9pA5GIHQNiONCnz9/PuVbMLb6BKrTbb+gU59b0z0JXZNYVeouvqamZthidqvyyw/9f/XqVTG5raVECF2zGuPfE3Xp0qV04cKFmkdv7N2OHDmy8k0do+3s2bPp6tWrGxtKT9kTuibY8a+UcZWuCS6ldPDgwZWv9xltFsTqs2u6J6EbEBu/Slvxrgdv/Av5CF2P2zx7EboBtZs3b6b79++vHmFxpx48C2L1OHWxF6EbUqz+KqgpZD14VaG9VanHbN69CD0HufGpd/661pcvX84x0sY4pMprx44d6eHDhxsj8QGyJPQc0MeFNvWeDtGC2BwN1uIQQs8Jb3yhxwLZZJAWxOZssDkPI/Sc4PJhpt6z4VkQm82oyz0I3YJmvje9sLDwxwi3bt1KJ06caDFqWYe6QsfWk9AteY83bB7Ofdb/Q3WFbtlgDQ8ndENgk3Yfv5Xl1sxkob3QddBsM4YgdEeMx99Pu1L/vcZA6I6a7R/DELojxk+fPk2XL19efRBCHnaj385yy6qj5mowDKEbwJq16/Pnz9PFixdJ/T9QFsRmdUz3/0/ojpnu2bMnbdmy5a9RN+J004JYx81VYzhC14DUdJc81cwLY/mD/KMtT7+/fv2a3r9/33S4dbf/0aNH07dv3/7IfyO+oA1ROEL3RH3SPeosdb56v3jxoqeoww977NixlReu6ouZJ5TE1YXQPbL+/v17ylerSduXL1+Ku1ofP3485bzGZyaLi4s9UjZ0lQChA/ph0i2t0RM8Smn2SR8r3eir/AGt9VcIQgdRP3To0Mr76vEtN33++OV6fmhefsHKW/XKnH/2vjmouSphCB3MPK/8ZonHm38kxHoTe9rso5SZR3B7tA5H6NYImw8wWjiadFUbyb4erm7jvzgyIrEezr151dbHEYQeuE6TrnD5lEbvsdfiqvgkkUt46zBwK3QSntCdYGw3yKT71tUR18pVO68D5Ac5jM8s8vnlP0tLS+1AOLo1AUK3RtjtANOmseNRou7tTptBVM/HFLvbHmgzGqHb0Ovx2Gkrx9NCVh9kP2nBrY9TdVuqD6rtxiR0O369Hz263TUSNkrWSYmNpv75HLZt25YeP37ce/4CNCNA6Ga8Bt+7zhS4r5PMC3T5E2W2tUuA0Gu3No3ObPTeuzr1bjTAlJ3z1dh75C5IxoxB6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQIHQIZkEQiCFA6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQ+A+sTBEnEQXhEgAAAABJRU5ErkJggg==", - mimeType: "image/png", - }, - }, - ], - }, - }, - validatorMetadata: [], - path: [1], - timestamp: 16784.899999976158, - }, - async reply() {}, - }, - { - type: "nodestart", - data: { - node: { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - content: { - role: "user", - parts: [ - { - inlineData: { - data: "iVBORw0KGgoAAAANSUhEUgAAAPQAAAC3CAYAAAAl43M8AAAAAXNSR0IArs4c6QAACb1JREFUeF7t3buO1EwTgOGGRURIcAEEcAecxSkjJOAQEBBwA0gQkAESISIn5wKAjBCEkBDitAtCIiQDcQmc2U+9+md/M8ww9tgu7/Y+lhBasLtcb9U77mnveDYtLy8vJxsCCBRBYBOhi6ijJBBYIUBojYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVMxpqezbty9t3rw5LS8vr+yS/379+vXKv9nKIkDoNVDP27dvpzt37qzKloV78+ZNJ2c2knnSYNu3b0+PHj3qJI5B1gYBQq+BOuzfvz9t2rTpjzPJUi8uLrY+u38J/fv377S0tNQ6hgHWDgFCD1yLAwcOTDyDLmTLMucXitGLxWjKXf25ixeNgREKXyFA6IHbYZrQXVyhx6/8CwsL6efPn3/MBvJ7aVs5BAg9cC0nTbfzKXVxhZ42djVlQg/cAB2HJ3THQJsON+0KvWvXrnTv3r2mw/2x//iUu/qfXcwAWp2cg3shQOhesNYf9PDhwyvT4NGWRct/ulqs2rt378rtqeqiWx7/x48f6d27d/VP1J7rggChBy7T58+f08mTJ1cXr379+tXZLauBUxN+AAKEHgC6kAj0RYDQfZE1LgIDECD0ANCFRKAvAoTui6xxERiAAKEHgC4kAn0RIHRfZI2LwAAECD0AdCER6IsAofsia1wEBiBA6AGgC4lAXwQI3RdZ4yIwAAFCDwBdSAT6IkDoGWTPnTuXPnz4sLJX/j3rt2/f9lUL4yLQmgChZyCsPsLHRw5b95sBeiZA6BmAqw8JIHTP3Wj41gQI7QrduomaDPDx48e0c+fOJofYtwEBQhO6Qbu02/XKlSvpyZMnaevWrenZs2ftBnP0RAKEbiB03tUzuOY3qfq4pevXr6fTp0/PP5gjCT1PD1gUm4fa5GOq6xH50Uv5CwZs3RJwhbYo1m1H/WO0qtC7d+9Od+/eDYu9UQIRmtBhvV6dcp85cyZdu3YtLPZGCUToGZW+ceNGevDgwepTMz3Ebz41Tp06lT59+rR6sLWI+TjOOorQswillNyLrgHJTKc9pA5GIHQNiONCnz9/PuVbMLb6BKrTbb+gU59b0z0JXZNYVeouvqamZthidqvyyw/9f/XqVTG5raVECF2zGuPfE3Xp0qV04cKFmkdv7N2OHDmy8k0do+3s2bPp6tWrGxtKT9kTuibY8a+UcZWuCS6ldPDgwZWv9xltFsTqs2u6J6EbEBu/Slvxrgdv/Av5CF2P2zx7EboBtZs3b6b79++vHmFxpx48C2L1OHWxF6EbUqz+KqgpZD14VaG9VanHbN69CD0HufGpd/661pcvX84x0sY4pMprx44d6eHDhxsj8QGyJPQc0MeFNvWeDtGC2BwN1uIQQs8Jb3yhxwLZZJAWxOZssDkPI/Sc4PJhpt6z4VkQm82oyz0I3YJmvje9sLDwxwi3bt1KJ06caDFqWYe6QsfWk9AteY83bB7Ofdb/Q3WFbtlgDQ8ndENgk3Yfv5Xl1sxkob3QddBsM4YgdEeMx99Pu1L/vcZA6I6a7R/DELojxk+fPk2XL19efRBCHnaj385yy6qj5mowDKEbwJq16/Pnz9PFixdJ/T9QFsRmdUz3/0/ojpnu2bMnbdmy5a9RN+J004JYx81VYzhC14DUdJc81cwLY/mD/KMtT7+/fv2a3r9/33S4dbf/0aNH07dv3/7IfyO+oA1ROEL3RH3SPeosdb56v3jxoqeoww977NixlReu6ouZJ5TE1YXQPbL+/v17ylerSduXL1+Ku1ofP3485bzGZyaLi4s9UjZ0lQChA/ph0i2t0RM8Smn2SR8r3eir/AGt9VcIQgdRP3To0Mr76vEtN33++OV6fmhefsHKW/XKnH/2vjmouSphCB3MPK/8ZonHm38kxHoTe9rso5SZR3B7tA5H6NYImw8wWjiadFUbyb4erm7jvzgyIrEezr151dbHEYQeuE6TrnD5lEbvsdfiqvgkkUt46zBwK3QSntCdYGw3yKT71tUR18pVO68D5Ac5jM8s8vnlP0tLS+1AOLo1AUK3RtjtANOmseNRou7tTptBVM/HFLvbHmgzGqHb0Ovx2Gkrx9NCVh9kP2nBrY9TdVuqD6rtxiR0O369Hz263TUSNkrWSYmNpv75HLZt25YeP37ce/4CNCNA6Ga8Bt+7zhS4r5PMC3T5E2W2tUuA0Gu3No3ObPTeuzr1bjTAlJ3z1dh75C5IxoxB6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQIHQIZkEQiCFA6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQ+A+sTBEnEQXhEgAAAABJRU5ErkJggg==", - mimeType: "image/png", - }, - }, - ], - }, - }, - path: [2], - timestamp: 16792.099999964237, - }, - async reply() {}, - }, - { - type: "output", - data: { - node: { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - outputs: { - content: { - role: "user", - parts: [ - { - inlineData: { - data: "iVBORw0KGgoAAAANSUhEUgAAAPQAAAC3CAYAAAAl43M8AAAAAXNSR0IArs4c6QAACb1JREFUeF7t3buO1EwTgOGGRURIcAEEcAecxSkjJOAQEBBwA0gQkAESISIn5wKAjBCEkBDitAtCIiQDcQmc2U+9+md/M8ww9tgu7/Y+lhBasLtcb9U77mnveDYtLy8vJxsCCBRBYBOhi6ijJBBYIUBojYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVMxpqezbty9t3rw5LS8vr+yS/379+vXKv9nKIkDoNVDP27dvpzt37qzKloV78+ZNJ2c2knnSYNu3b0+PHj3qJI5B1gYBQq+BOuzfvz9t2rTpjzPJUi8uLrY+u38J/fv377S0tNQ6hgHWDgFCD1yLAwcOTDyDLmTLMucXitGLxWjKXf25ixeNgREKXyFA6IHbYZrQXVyhx6/8CwsL6efPn3/MBvJ7aVs5BAg9cC0nTbfzKXVxhZ42djVlQg/cAB2HJ3THQJsON+0KvWvXrnTv3r2mw/2x//iUu/qfXcwAWp2cg3shQOhesNYf9PDhwyvT4NGWRct/ulqs2rt378rtqeqiWx7/x48f6d27d/VP1J7rggChBy7T58+f08mTJ1cXr379+tXZLauBUxN+AAKEHgC6kAj0RYDQfZE1LgIDECD0ANCFRKAvAoTui6xxERiAAKEHgC4kAn0RIHRfZI2LwAAECD0AdCER6IsAofsia1wEBiBA6AGgC4lAXwQI3RdZ4yIwAAFCDwBdSAT6IkDoGWTPnTuXPnz4sLJX/j3rt2/f9lUL4yLQmgChZyCsPsLHRw5b95sBeiZA6BmAqw8JIHTP3Wj41gQI7QrduomaDPDx48e0c+fOJofYtwEBQhO6Qbu02/XKlSvpyZMnaevWrenZs2ftBnP0RAKEbiB03tUzuOY3qfq4pevXr6fTp0/PP5gjCT1PD1gUm4fa5GOq6xH50Uv5CwZs3RJwhbYo1m1H/WO0qtC7d+9Od+/eDYu9UQIRmtBhvV6dcp85cyZdu3YtLPZGCUToGZW+ceNGevDgwepTMz3Ebz41Tp06lT59+rR6sLWI+TjOOorQswillNyLrgHJTKc9pA5GIHQNiONCnz9/PuVbMLb6BKrTbb+gU59b0z0JXZNYVeouvqamZthidqvyyw/9f/XqVTG5raVECF2zGuPfE3Xp0qV04cKFmkdv7N2OHDmy8k0do+3s2bPp6tWrGxtKT9kTuibY8a+UcZWuCS6ldPDgwZWv9xltFsTqs2u6J6EbEBu/Slvxrgdv/Av5CF2P2zx7EboBtZs3b6b79++vHmFxpx48C2L1OHWxF6EbUqz+KqgpZD14VaG9VanHbN69CD0HufGpd/661pcvX84x0sY4pMprx44d6eHDhxsj8QGyJPQc0MeFNvWeDtGC2BwN1uIQQs8Jb3yhxwLZZJAWxOZssDkPI/Sc4PJhpt6z4VkQm82oyz0I3YJmvje9sLDwxwi3bt1KJ06caDFqWYe6QsfWk9AteY83bB7Ofdb/Q3WFbtlgDQ8ndENgk3Yfv5Xl1sxkob3QddBsM4YgdEeMx99Pu1L/vcZA6I6a7R/DELojxk+fPk2XL19efRBCHnaj385yy6qj5mowDKEbwJq16/Pnz9PFixdJ/T9QFsRmdUz3/0/ojpnu2bMnbdmy5a9RN+J004JYx81VYzhC14DUdJc81cwLY/mD/KMtT7+/fv2a3r9/33S4dbf/0aNH07dv3/7IfyO+oA1ROEL3RH3SPeosdb56v3jxoqeoww977NixlReu6ouZJ5TE1YXQPbL+/v17ylerSduXL1+Ku1ofP3485bzGZyaLi4s9UjZ0lQChA/ph0i2t0RM8Smn2SR8r3eir/AGt9VcIQgdRP3To0Mr76vEtN33++OV6fmhefsHKW/XKnH/2vjmouSphCB3MPK/8ZonHm38kxHoTe9rso5SZR3B7tA5H6NYImw8wWjiadFUbyb4erm7jvzgyIrEezr151dbHEYQeuE6TrnD5lEbvsdfiqvgkkUt46zBwK3QSntCdYGw3yKT71tUR18pVO68D5Ac5jM8s8vnlP0tLS+1AOLo1AUK3RtjtANOmseNRou7tTptBVM/HFLvbHmgzGqHb0Ovx2Gkrx9NCVh9kP2nBrY9TdVuqD6rtxiR0O369Hz263TUSNkrWSYmNpv75HLZt25YeP37ce/4CNCNA6Ga8Bt+7zhS4r5PMC3T5E2W2tUuA0Gu3No3ObPTeuzr1bjTAlJ3z1dh75C5IxoxB6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQIHQIZkEQiCFA6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQ+A+sTBEnEQXhEgAAAABJRU5ErkJggg==", - mimeType: "image/png", - }, - }, - ], - }, - }, - path: [2], - timestamp: 16797.5, - bubbled: false, - }, - async reply() {}, - }, - { - type: "nodeend", - data: { - node: { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - content: { - role: "user", - parts: [ - { - inlineData: { - data: "iVBORw0KGgoAAAANSUhEUgAAAPQAAAC3CAYAAAAl43M8AAAAAXNSR0IArs4c6QAACb1JREFUeF7t3buO1EwTgOGGRURIcAEEcAecxSkjJOAQEBBwA0gQkAESISIn5wKAjBCEkBDitAtCIiQDcQmc2U+9+md/M8ww9tgu7/Y+lhBasLtcb9U77mnveDYtLy8vJxsCCBRBYBOhi6ijJBBYIUBojYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVEypIEBoPYBAQQQIXVAxpYIAofUAAgURIHRBxZQKAoTWAwgURIDQBRVTKggQWg8gUBABQhdUTKkgQGg9gEBBBAhdUDGlggCh9QACBREgdEHFlAoChNYDCBREgNAFFVMqCBBaDyBQEAFCF1RMqSBAaD2AQEEECF1QMaWCAKH1AAIFESB0QcWUCgKE1gMIFESA0AUVUyoIEFoPIFAQAUIXVMxpqezbty9t3rw5LS8vr+yS/379+vXKv9nKIkDoNVDP27dvpzt37qzKloV78+ZNJ2c2knnSYNu3b0+PHj3qJI5B1gYBQq+BOuzfvz9t2rTpjzPJUi8uLrY+u38J/fv377S0tNQ6hgHWDgFCD1yLAwcOTDyDLmTLMucXitGLxWjKXf25ixeNgREKXyFA6IHbYZrQXVyhx6/8CwsL6efPn3/MBvJ7aVs5BAg9cC0nTbfzKXVxhZ42djVlQg/cAB2HJ3THQJsON+0KvWvXrnTv3r2mw/2x//iUu/qfXcwAWp2cg3shQOhesNYf9PDhwyvT4NGWRct/ulqs2rt378rtqeqiWx7/x48f6d27d/VP1J7rggChBy7T58+f08mTJ1cXr379+tXZLauBUxN+AAKEHgC6kAj0RYDQfZE1LgIDECD0ANCFRKAvAoTui6xxERiAAKEHgC4kAn0RIHRfZI2LwAAECD0AdCER6IsAofsia1wEBiBA6AGgC4lAXwQI3RdZ4yIwAAFCDwBdSAT6IkDoGWTPnTuXPnz4sLJX/j3rt2/f9lUL4yLQmgChZyCsPsLHRw5b95sBeiZA6BmAqw8JIHTP3Wj41gQI7QrduomaDPDx48e0c+fOJofYtwEBQhO6Qbu02/XKlSvpyZMnaevWrenZs2ftBnP0RAKEbiB03tUzuOY3qfq4pevXr6fTp0/PP5gjCT1PD1gUm4fa5GOq6xH50Uv5CwZs3RJwhbYo1m1H/WO0qtC7d+9Od+/eDYu9UQIRmtBhvV6dcp85cyZdu3YtLPZGCUToGZW+ceNGevDgwepTMz3Ebz41Tp06lT59+rR6sLWI+TjOOorQswillNyLrgHJTKc9pA5GIHQNiONCnz9/PuVbMLb6BKrTbb+gU59b0z0JXZNYVeouvqamZthidqvyyw/9f/XqVTG5raVECF2zGuPfE3Xp0qV04cKFmkdv7N2OHDmy8k0do+3s2bPp6tWrGxtKT9kTuibY8a+UcZWuCS6ldPDgwZWv9xltFsTqs2u6J6EbEBu/Slvxrgdv/Av5CF2P2zx7EboBtZs3b6b79++vHmFxpx48C2L1OHWxF6EbUqz+KqgpZD14VaG9VanHbN69CD0HufGpd/661pcvX84x0sY4pMprx44d6eHDhxsj8QGyJPQc0MeFNvWeDtGC2BwN1uIQQs8Jb3yhxwLZZJAWxOZssDkPI/Sc4PJhpt6z4VkQm82oyz0I3YJmvje9sLDwxwi3bt1KJ06caDFqWYe6QsfWk9AteY83bB7Ofdb/Q3WFbtlgDQ8ndENgk3Yfv5Xl1sxkob3QddBsM4YgdEeMx99Pu1L/vcZA6I6a7R/DELojxk+fPk2XL19efRBCHnaj385yy6qj5mowDKEbwJq16/Pnz9PFixdJ/T9QFsRmdUz3/0/ojpnu2bMnbdmy5a9RN+J004JYx81VYzhC14DUdJc81cwLY/mD/KMtT7+/fv2a3r9/33S4dbf/0aNH07dv3/7IfyO+oA1ROEL3RH3SPeosdb56v3jxoqeoww977NixlReu6ouZJ5TE1YXQPbL+/v17ylerSduXL1+Ku1ofP3485bzGZyaLi4s9UjZ0lQChA/ph0i2t0RM8Smn2SR8r3eir/AGt9VcIQgdRP3To0Mr76vEtN33++OV6fmhefsHKW/XKnH/2vjmouSphCB3MPK/8ZonHm38kxHoTe9rso5SZR3B7tA5H6NYImw8wWjiadFUbyb4erm7jvzgyIrEezr151dbHEYQeuE6TrnD5lEbvsdfiqvgkkUt46zBwK3QSntCdYGw3yKT71tUR18pVO68D5Ac5jM8s8vnlP0tLS+1AOLo1AUK3RtjtANOmseNRou7tTptBVM/HFLvbHmgzGqHb0Ovx2Gkrx9NCVh9kP2nBrY9TdVuqD6rtxiR0O369Hz263TUSNkrWSYmNpv75HLZt25YeP37ce/4CNCNA6Ga8Bt+7zhS4r5PMC3T5E2W2tUuA0Gu3No3ObPTeuzr1bjTAlJ3z1dh75C5IxoxB6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQIHQIZkEQiCFA6BjOoiAQQoDQIZgFQSCGAKFjOIuCQAgBQodgFgSBGAKEjuEsCgIhBAgdglkQBGIIEDqGsygIhBAgdAhmQRCIIUDoGM6iIBBCgNAhmAVBIIYAoWM4i4JACAFCh2AWBIEYAoSO4SwKAiEECB2CWRAEYggQOoazKAiEECB0CGZBEIghQOgYzqIgEEKA0CGYBUEghgChYziLgkAIAUKHYBYEgRgChI7hLAoCIQQIHYJZEARiCBA6hrMoCIQQ+A+sTBEnEQXhEgAAAABJRU5ErkJggg==", - mimeType: "image/png", - }, - }, - ], - }, - }, - validatorMetadata: [], - path: [2], - timestamp: 16803.69999998808, - outputs: {}, - }, - async reply() {}, - }, - { type: "graphend", data: { path: [], timestamp: 16807 }, async reply() {} }, -]; diff --git a/packages/data-store/tests/run/placeholder.nodejs.test.ts b/packages/data-store/tests/run/placeholder.nodejs.test.ts deleted file mode 100644 index ad1b63c5b51..00000000000 --- a/packages/data-store/tests/run/placeholder.nodejs.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -test("data-store", (t) => { - t.truthy(true); -}); diff --git a/packages/data-store/tests/run/simple-run.ts b/packages/data-store/tests/run/simple-run.ts deleted file mode 100644 index 3eb55a685da..00000000000 --- a/packages/data-store/tests/run/simple-run.ts +++ /dev/null @@ -1,322 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { HarnessRunResult } from "@google-labs/breadboard/harness"; - -export const results: HarnessRunResult[] = [ - { - type: "graphstart", - data: { - graph: { - url: "idb://default/blank-board.bgl.json", - title: "Blank board", - description: - "A blank board. Use it as a starting point for your creations.", - $schema: - "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.5.1/packages/schema/breadboard.schema.json", - version: "0.0.1", - edges: [ - { - from: "input-45dd0a3d", - to: "output-b8d7ce06", - out: "content", - in: "content", - }, - ], - nodes: [ - { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - ], - kits: [], - }, - path: [], - timestamp: 2448.5, - }, - async reply() {}, - }, - { - type: "nodestart", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - path: [1], - timestamp: 2458.5, - }, - async reply() {}, - }, - { - type: "input", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputArguments: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - path: [1], - bubbled: false, - timestamp: 2467.5, - }, - async reply() {}, - }, - { - type: "nodeend", - data: { - node: { - id: "input-45dd0a3d", - type: "input", - metadata: { visual: { x: 54, y: 193, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - outputs: { content: { role: "user", parts: [{ text: "Plain text" }] } }, - validatorMetadata: [], - path: [1], - timestamp: 108244.10000002384, - }, - async reply() {}, - }, - { - type: "nodestart", - data: { - node: { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - content: { role: "user", parts: [{ text: "Plain text" }] }, - }, - path: [2], - timestamp: 108251.40000003576, - }, - async reply() {}, - }, - { - type: "output", - data: { - node: { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - outputs: { content: { role: "user", parts: [{ text: "Plain text" }] } }, - path: [2], - timestamp: 108257.90000003576, - bubbled: false, - }, - async reply() {}, - }, - { - type: "nodeend", - data: { - node: { - id: "output-b8d7ce06", - type: "output", - metadata: { visual: { x: 340, y: 169, collapsed: false } }, - configuration: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - }, - }, - inputs: { - schema: { - properties: { - content: { - type: "object", - title: "Content", - examples: [], - behavior: ["llm-content"], - }, - }, - type: "object", - required: [], - }, - content: { role: "user", parts: [{ text: "Plain text" }] }, - }, - validatorMetadata: [], - path: [2], - timestamp: 108272, - outputs: {}, - }, - async reply() {}, - }, - { - type: "graphend", - data: { path: [], timestamp: 108274.70000004768 }, - async reply() {}, - }, -]; diff --git a/packages/data-store/tsconfig.json b/packages/data-store/tsconfig.json deleted file mode 100644 index 16baf0087bc..00000000000 --- a/packages/data-store/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "outDir": "./dist", - "resolveJsonModule": true, - "esModuleInterop": true - }, - "include": ["src/**/*", "tests/**/*"], - "exclude": ["bundled"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/discovery-types/.eslintrc b/packages/discovery-types/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/discovery-types/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/discovery-types/.npmignore b/packages/discovery-types/.npmignore deleted file mode 100644 index 7ddb2133685..00000000000 --- a/packages/discovery-types/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -tsconfig.tsbuildinfo diff --git a/packages/discovery-types/README.md b/packages/discovery-types/README.md deleted file mode 100644 index 8c2ebe44657..00000000000 --- a/packages/discovery-types/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Breadboard Discovery Types - -Made primarily to read the PaLM API Discovery doc and spit out nice TypeScript declarations. - -To use: - -```ts -import { config } from "dotenv"; - -import { toTypes } from "@google-labs/discovery-types"; - -config(); - -const DISCOVER_DOC_URL = - "https://generativelanguage.googleapis.com/$discovery/rest?version=v1beta2"; -const { API_KEY } = process.env; -if (!API_KEY) throw new Error("API_KEY is not defined"); - -const response = await fetch(`${DISCOVER_DOC_URL}&key=${API_KEY}`); -const doc = await response.json(); - -const types = toTypes(doc); -console.log(types); -``` diff --git a/packages/discovery-types/package.json b/packages/discovery-types/package.json deleted file mode 100644 index 2d86d5f6f15..00000000000 --- a/packages/discovery-types/package.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "name": "@google-labs/discovery-types", - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "private": true, - "version": "0.0.1", - "description": "Simplest possible Discovery doc-to-TypeScript definitions converter", - "main": "./dist/src/index.js", - "exports": "./dist/src/index.js", - "types": "dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "test": "wireit", - "build": "wireit", - "build:tsc": "wireit", - "lint": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "build:tsc" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "files": [ - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/", - "!dist/**/*.min.js{,.map}" - ], - "clean": "if-file-deleted" - }, - "test": { - "command": "ava", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - } - }, - "repository": { - "directory": "packages/discovery-types", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src" - ], - "ava": { - "timeout": "30s", - "files": [ - "tests/**/*.ts" - ], - "workerThreads": false, - "typescript": { - "rewritePaths": { - "./": "dist/" - }, - "compile": false - } - }, - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@types/prettier": "^3.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "typescript": "^5.6.2" - }, - "dependencies": { - "dotenv": "^16.4.5", - "prettier": "^3.3.2" - } -} diff --git a/packages/discovery-types/src/converter.ts b/packages/discovery-types/src/converter.ts deleted file mode 100644 index fa5faaa0bc1..00000000000 --- a/packages/discovery-types/src/converter.ts +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * This is a minimal implementation of the Discovery Document to TypeScript converter. - * It is not intended to be a complete implementation, rather just enough code - * to parse the Discovery doc for https://developers.generativeai.google/api/rest/generativelanguage - * and produce decent TypeScript definitions for the request/response objects. - */ - -export interface Schema { - id: string; - $ref: string; - readonly: boolean; - required: boolean; - description: string; - enum?: string[]; - enumDescriptions?: string[]; - type: string; - items: Schema; - properties: Record; -} - -export interface DiscoveryDoc { - schemas: Record; -} - -const sorted = (o: Record): [string, Schema][] => { - const result = Object.entries(o); - result.sort(); - return result; -}; - -const toInterface = (schema: Schema): string => { - const name = schema.id; - const comment = toComment(schema.description); - const type = toType(schema); - return `${comment}export interface ${name} ${type}`; -}; - -const toType = (schema: Schema): string => { - if (schema.$ref) return schema.$ref; - if (schema.enum) return toEnum(schema); - if (schema.type == "integer") return "number"; - if (schema.type == "array") return toArray(schema.items); - if (schema.type != "object") return schema.type; - - return `{\n${sorted(schema.properties) - .map(([name, property]) => { - const comment = toComment(property.description); - const isRequired = comment && comment.startsWith("Required."); - const readonly = property.readonly ? "readonly" : ""; - const optional = property.required || isRequired ? "" : "?"; - const type = toType(property); - return `${comment}${readonly}${name}${optional}: ${type}`; - }) - .join("\n")}\n}`; -}; - -const toArray = (items: Schema): string => { - return `${toType(items)}[]`; -}; - -const toEnum = (schema: Schema): string => { - const values = schema.enum || []; - return `${values.map((v) => `"${v}"`).join(" | ")}`; -}; - -const toComment = (value: string): string => { - return `\n/**\n * ${value - .split("\n") - .join("\n * ") - .replace(/\*\//g, "*\\/")} */\n`; -}; - -export const fromDoc = (doc: DiscoveryDoc): string => { - return sorted(doc.schemas) - .map(([_name, schema]) => toInterface(schema)) - .join("\n"); -}; diff --git a/packages/discovery-types/src/index.ts b/packages/discovery-types/src/index.ts deleted file mode 100644 index 3e323a0677f..00000000000 --- a/packages/discovery-types/src/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import prettier from "prettier"; - -import { fromDoc, DiscoveryDoc } from "./converter.js"; - -export const toTypes = (o: unknown) => { - const doc = o as DiscoveryDoc; - const types = fromDoc(doc); - const formatted = prettier.format(types, { - parser: "typescript", - arrowParens: "always", - printWidth: 80, - semi: true, - tabWidth: 2, - trailingComma: "es5", - useTabs: false, - }); - return formatted; -}; diff --git a/packages/discovery-types/tests/index.ts b/packages/discovery-types/tests/index.ts deleted file mode 100644 index 76be3ca0a36..00000000000 --- a/packages/discovery-types/tests/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -test("discovery-types", async (t) => { - t.pass(); -}); diff --git a/packages/discovery-types/tsconfig.json b/packages/discovery-types/tsconfig.json deleted file mode 100644 index 1ff943cd641..00000000000 --- a/packages/discovery-types/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "outDir": "./dist" - }, - "include": ["src/**/*", "tests/**/*"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/example-boards/.eslintrc b/packages/example-boards/.eslintrc deleted file mode 100644 index a6e37a112d2..00000000000 --- a/packages/example-boards/.eslintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, - "ignorePatterns": ["build", "dist"], -} diff --git a/packages/example-boards/.npmignore b/packages/example-boards/.npmignore deleted file mode 100644 index 7ddb2133685..00000000000 --- a/packages/example-boards/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -tsconfig.tsbuildinfo diff --git a/packages/example-boards/CHANGELOG.md b/packages/example-boards/CHANGELOG.md deleted file mode 100644 index 21a2431994c..00000000000 --- a/packages/example-boards/CHANGELOG.md +++ /dev/null @@ -1,284 +0,0 @@ -# @breadboard-ai/example-boards - -## 0.3.2 - -### Patch Changes - -- Updated dependencies [49e2740] -- Updated dependencies [323216f] -- Updated dependencies [54c8197] -- Updated dependencies [f94f498] -- Updated dependencies [703f17d] -- Updated dependencies [6136d87] -- Updated dependencies [0273985] -- Updated dependencies [f5d3111] -- Updated dependencies [cb8c99a] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [8f9fddf] -- Updated dependencies [2fa05f0] -- Updated dependencies [4e0a4f6] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [f71bcfb] -- Updated dependencies [a104fa7] -- Updated dependencies [f0b5ccc] -- Updated dependencies [8a1b8c4] -- Updated dependencies [3188607] -- Updated dependencies [58d2e8c] -- Updated dependencies [9797718] -- Updated dependencies [679719b] -- Updated dependencies [88298d5] -- Updated dependencies [b673bfa] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [feeed7a] -- Updated dependencies [4cc71ee] -- Updated dependencies [8330f0c] -- Updated dependencies [9b62fc2] -- Updated dependencies [a039d2e] -- Updated dependencies [e63b5dd] -- Updated dependencies [1423647] -- Updated dependencies [74d50d4] -- Updated dependencies [9783ba8] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [9ce8ad3] -- Updated dependencies [7fdf9c2] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [91fe8bb] -- Updated dependencies [e38bf19] -- Updated dependencies [100fc95] -- Updated dependencies [4423c35] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [78d6394] -- Updated dependencies [5834c81] -- Updated dependencies [d7606d3] -- Updated dependencies [0ef793f] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] -- Updated dependencies [9c04caa] -- Updated dependencies [e026112] -- Updated dependencies [94759f7] -- Updated dependencies [281ab28] -- Updated dependencies [e74ee2f] -- Updated dependencies [5fc6e8b] - - @breadboard-ai/build@0.10.0 - - @google-labs/gemini-kit@0.8.0 - - @breadboard-ai/google-drive-kit@0.2.4 - - @breadboard-ai/python-wasm@0.1.6 - - @google-labs/core-kit@0.15.0 - - @google-labs/json-kit@0.3.8 - - @google-labs/agent-kit@0.12.0 - - @google-labs/breadboard@0.27.0 - - @google-labs/template-kit@0.3.10 - - @google-labs/node-nursery-web@1.3.2 - - @breadboard-ai/manifest@0.4.4 - - @google-labs/palm-kit@0.1.4 - -## 0.3.1 - -### Patch Changes - -- 3cb60e9: Update gemini-vision example to use regular gemini model -- Updated dependencies [3b9229d] -- Updated dependencies [bbcdd2d] -- Updated dependencies [9ed58cf] -- Updated dependencies [13c27cb] -- Updated dependencies [7f2ef33] -- Updated dependencies [85fb144] -- Updated dependencies [3cb60e9] -- Updated dependencies [c1dc2a4] -- Updated dependencies [7d46a63] -- Updated dependencies [1a70e7d] -- Updated dependencies [bac2e35] -- Updated dependencies [ec2fedd] - - @google-labs/agent-kit@0.11.0 - - @breadboard-ai/build@0.9.1 - - @google-labs/gemini-kit@0.7.0 - - @google-labs/core-kit@0.14.1 - - @google-labs/breadboard@0.26.0 - - @google-labs/json-kit@0.3.7 - - @breadboard-ai/manifest@0.4.3 - - @google-labs/node-nursery-web@1.3.1 - - @google-labs/palm-kit@0.1.3 - - @google-labs/template-kit@0.3.9 - -## 0.3.0 - -### Minor Changes - -- 05e3ff2: Added two new tools - -### Patch Changes - -- Updated dependencies [cc5f4b6] -- Updated dependencies [1a6a9cf] -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [78a6bcf] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [a940b87] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [374ea85] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [e0dccfe] -- Updated dependencies [c397d53] -- Updated dependencies [f93ec06] -- Updated dependencies [cc5f4b6] -- Updated dependencies [398bf4f] -- Updated dependencies [a940b87] -- Updated dependencies [494d5ca] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [ee1f9ca] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @breadboard-ai/build@0.9.0 - - @google-labs/agent-kit@0.10.0 - - @google-labs/breadboard@0.25.0 - - @google-labs/gemini-kit@0.6.0 - - @google-labs/core-kit@0.14.0 - - @breadboard-ai/google-drive-kit@0.2.3 - - @breadboard-ai/python-wasm@0.1.5 - - @google-labs/node-nursery-web@1.3.0 - - @google-labs/json-kit@0.3.6 - - @google-labs/template-kit@0.3.8 - - @breadboard-ai/manifest@0.4.2 - - @google-labs/palm-kit@0.1.2 - -## 0.2.1 - -### Patch Changes - -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [c5c39be] -- Updated dependencies [1dc645a] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [c04cff0] -- Updated dependencies [d88c37b] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - - @google-labs/agent-kit@0.9.1 - - @google-labs/node-nursery-web@1.2.0 - - @google-labs/core-kit@0.13.0 - - @breadboard-ai/build@0.8.1 - - @google-labs/gemini-kit@0.5.4 - - @google-labs/json-kit@0.3.5 - - @breadboard-ai/manifest@0.4.1 - - @google-labs/palm-kit@0.1.1 - - @google-labs/template-kit@0.3.7 - - @breadboard-ai/google-drive-kit@0.2.2 - -## 0.2.0 - -### Minor Changes - -- 5f6d97c: Separate playground and examples - -### Patch Changes - -- 9a2ffab: Unpin @breadboard-ai/build dependency from being overly constrained -- Updated dependencies [cb0f513] -- Updated dependencies [ad8aa22] -- Updated dependencies [0519ebb] -- Updated dependencies [1e1be2a] -- Updated dependencies [6d2939e] -- Updated dependencies [15b6171] -- Updated dependencies [5c5b665] -- Updated dependencies [2b094a3] -- Updated dependencies [fa93c3f] -- Updated dependencies [8d2e618] -- Updated dependencies [f78ec0a] -- Updated dependencies [215bd15] -- Updated dependencies [2b9ef5b] -- Updated dependencies [8dbbe20] -- Updated dependencies [a0852df] -- Updated dependencies [38e3232] -- Updated dependencies [7298a47] -- Updated dependencies [ea7e2a1] -- Updated dependencies [8edcbc0] -- Updated dependencies [8db38aa] -- Updated dependencies [5f6d97c] -- Updated dependencies [9a2ffab] -- Updated dependencies [b049e00] -- Updated dependencies [0a846ff] -- Updated dependencies [b99472b] -- Updated dependencies [4bfaec5] -- Updated dependencies [2312443] -- Updated dependencies [1341291] -- Updated dependencies [b76f9a1] -- Updated dependencies [6ffa89c] -- Updated dependencies [15ae381] - - @breadboard-ai/google-drive-kit@0.2.1 - - @breadboard-ai/build@0.8.0 - - @google-labs/gemini-kit@0.5.3 - - @google-labs/breadboard@0.23.0 - - @google-labs/core-kit@0.12.0 - - @google-labs/template-kit@0.3.6 - - @google-labs/agent-kit@0.9.0 - - @google-labs/json-kit@0.3.4 - - @breadboard-ai/manifest@0.4.0 - - @breadboard-ai/python-wasm@0.1.4 - - @google-labs/palm-kit@0.1.0 - - @google-labs/node-nursery-web@1.1.6 - -## 0.1.1 - -### Patch Changes - -- Updated dependencies [a925cf0] -- Updated dependencies [f2d9839] -- Updated dependencies [f4d2416] -- Updated dependencies [bc94299] -- Updated dependencies [f4397b9] -- Updated dependencies [166f290] -- Updated dependencies [da43bb5] -- Updated dependencies [5cf08f1] -- Updated dependencies [9d93cf8] -- Updated dependencies [9d93cf8] -- Updated dependencies [bc8dcdd] -- Updated dependencies [ffbf163] -- Updated dependencies [8928fb7] -- Updated dependencies [9d93cf8] -- Updated dependencies [d6706f2] -- Updated dependencies [5f6432b] -- Updated dependencies [5447426] -- Updated dependencies [4da35e5] -- Updated dependencies [26e1099] -- Updated dependencies [7e1f01c] -- Updated dependencies [a9def5c] - - @google-labs/breadboard@0.22.0 - - @breadboard-ai/google-drive-kit@0.2.0 - - @google-labs/core-kit@0.11.0 - - @google-labs/agent-kit@0.8.1 - - @breadboard-ai/build@0.7.1 - - @breadboard-ai/manifest@0.3.0 - - @google-labs/gemini-kit@0.5.2 - - @google-labs/json-kit@0.3.3 - - @google-labs/node-nursery-web@1.1.5 - - @google-labs/palm-kit@0.0.16 - - @google-labs/template-kit@0.3.5 - - @breadboard-ai/python-wasm@0.1.3 diff --git a/packages/example-boards/README.md b/packages/example-boards/README.md deleted file mode 100644 index 1926be1e39f..00000000000 --- a/packages/example-boards/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Breadboard Example Boards - -The example boards sent through to the Visual Editor. diff --git a/packages/example-boards/examples-boards.json b/packages/example-boards/examples-boards.json deleted file mode 100644 index f402e0bc141..00000000000 --- a/packages/example-boards/examples-boards.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "boards": [ - { - "title": "Basics: Blank board", - "reference": "/example-boards/examples/blank.json", - "version": "0.0.1" - }, - { - "title": "Cookbook: Split an Array with JSONata", - "reference": "/example-boards/examples/array-split-jsonata.bgl.json", - "version": "0.0.1", - "tags": [] - }, - { - "title": "Cookbook: Fetch Data", - "reference": "/example-boards/examples/google-books-api.json", - "version": "0.0.1" - }, - { - "title": "Guide: Hello, Specialist", - "reference": "/example-boards/examples/hello-specialist.bgl.json", - "version": "0.0.1" - }, - { - "title": "Guide: My Librarian", - "reference": "/example-boards/examples/librarian.bgl.json", - "version": "0.0.1", - "tags": [] - }, - { - "title": "Guide: Novel Generator", - "reference": "/example-boards/examples/novel-generator.bgl.json", - "version": "0.0.1", - "tags": [] - }, - { - "title": "Guide: Rhyme of the Day", - "reference": "/example-boards/examples/rhyme-of-the-day.bgl.json", - "version": "0.0.1" - }, - { - "title": "Guide: Social Media Post Creator", - "reference": "/example-boards/examples/social-media-post-creator.bgl.json", - "version": "0.0.1", - "tags": [] - }, - { - "title": "Tool: Novel Developer", - "reference": "/example-boards/examples/tool-novel-developer.bgl.json", - "version": "0.0.1", - "tags": [ - "tool" - ] - }, - { - "title": "Tool: Novel Outliner", - "reference": "/example-boards/examples/tool-novel-outliner.bgl.json", - "version": "0.0.1", - "tags": [ - "tool" - ] - }, - { - "title": "Tool: Today's Date", - "reference": "/example-boards/examples/tool-todays-date.bgl.json", - "version": "0.0.1", - "tags": [ - "tool" - ] - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/package.json b/packages/example-boards/package.json deleted file mode 100644 index d28c5090e46..00000000000 --- a/packages/example-boards/package.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "name": "@breadboard-ai/example-boards", - "version": "0.3.2", - "description": "A collection of example boards", - "main": "./build/make-graphs.js", - "exports": { - "./examples-boards.json": "./examples-boards.json", - "./playground-boards.json": "./playground-boards.json", - "./example-boards/*.json": "./example-boards/*.json" - }, - "types": "build/make-graphs.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "build:tsc": "wireit", - "generate:graphs": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "../agent-kit:build", - "../breadboard:build", - "../build:build", - "../core-kit:build", - "../gemini-kit:build", - "../google-drive-kit:build", - "../json-kit:build", - "../template-kit:build", - "../node-nursery-web:build", - "../palm-kit:build", - "../python-wasm:build", - "../manifest:build", - "build:tsc", - "generate:graphs" - ] - }, - "typescript-files-and-deps": { - "dependencies": [ - "../agent-kit:build:tsc", - "../breadboard:build:tsc", - "../build:build:tsc", - "../core-kit:build:tsc", - "../gemini-kit:build:tsc", - "../google-drive-kit:build:tsc", - "../json-kit:build:tsc", - "../template-kit:build:tsc", - "../node-nursery-web:build:tsc", - "../palm-kit:build:tsc", - "../python-wasm:build:tsc", - "../manifest:build" - ], - "files": [ - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "typescript-files-and-deps" - ], - "files": [], - "output": [ - "build/", - "!build/**/*.min.js{,.map}" - ], - "clean": "if-file-deleted" - }, - "generate:graphs": { - "command": "tsx src/make-graphs.ts", - "dependencies": [ - "../agent-kit:build", - "../breadboard:build:tsc", - "../build:build:tsc", - "../core-kit:build", - "../gemini-kit:build", - "../google-drive-kit:build", - "../json-kit:build", - "../manifest:build:ts", - "../node-nursery-web:build", - "../palm-kit:build", - "../template-kit:build" - ], - "files": [ - "src/make-graphs.ts", - "src/boards/**/*.ts", - "src/boards/**/*.json" - ], - "output": [ - "example-boards.json", - "playground-boards.json", - "example-boards/**/*.json", - "docs/graphs/**/*.md" - ] - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - } - }, - "repository": { - "directory": "packages/example-boards", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "build/" - ], - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/example-boards#readme", - "devDependencies": { - "@google-labs/tsconfig": "^0.0.1", - "tsx": "^4.19.1", - "typescript": "^5.6.2" - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/google-drive-kit": "0.2.4", - "@breadboard-ai/manifest": "^0.4.4", - "@breadboard-ai/python-wasm": "0.1.6", - "@google-labs/agent-kit": "^0.12.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/gemini-kit": "^0.8.0", - "@google-labs/json-kit": "^0.3.8", - "@google-labs/node-nursery-web": "^1.3.2", - "@google-labs/palm-kit": "^0.1.4", - "@google-labs/template-kit": "^0.3.10" - } -} diff --git a/packages/example-boards/playground-boards.json b/packages/example-boards/playground-boards.json deleted file mode 100644 index ec73b7fe07e..00000000000 --- a/packages/example-boards/playground-boards.json +++ /dev/null @@ -1,275 +0,0 @@ -{ - "boards": [ - { - "title": "Audio", - "reference": "/example-boards/playground/audio.json", - "version": "0.1.0" - }, - { - "title": "Blank board", - "reference": "/example-boards/playground/blank.json", - "version": "0.0.1" - }, - { - "title": "Error Board", - "reference": "/example-boards/playground/error.json", - "version": "0.1.0" - }, - { - "title": "Gemini Simple", - "reference": "/example-boards/playground/gemini-simple.json", - "version": "0.1.0" - }, - { - "title": "Google Custom Search Engine Tool", - "reference": "/example-boards/playground/google-custom-search-engine.json", - "version": "0.2.0" - }, - { - "title": "Hacker News Algolia Items", - "reference": "/example-boards/playground/hacker-news-algolia-items.json", - "version": "0.1.0" - }, - { - "title": "Hacker News Angolia Search", - "reference": "/example-boards/playground/hacker-news-algolia-search.json", - "version": "0.1.0" - }, - { - "title": "Hacker News Firebase API Story by ID", - "reference": "/example-boards/playground/hacker-news-firebase-story-from-id.json", - "version": "0.1.0" - }, - { - "title": "Hacker News Firebase Top Story IDs", - "reference": "/example-boards/playground/hacker-news-firebase-top-story-ids.json", - "version": "0.1.0" - }, - { - "title": "Hacker News Angolia Simplified Comment Search ", - "reference": "/example-boards/playground/hacker-news-simplified-algolia-comment-search.json", - "version": "0.1.0" - }, - { - "title": "Hacker News Angolia Simplified Search", - "reference": "/example-boards/playground/hacker-news-simplified-algolia-search.json", - "version": "0.1.0" - }, - { - "title": "Hacker News Angolia Simplified Story Search", - "reference": "/example-boards/playground/hacker-news-simplified-algolia-story-search.json", - "version": "0.1.0" - }, - { - "title": "Hugging Face Fill Mask", - "reference": "/example-boards/playground/hugging-face-fill-mask.json", - "version": "" - }, - { - "title": "Hugging Face Labelling Board", - "reference": "/example-boards/playground/hugging-face-labelling.json", - "version": "" - }, - { - "title": "Hugging Face Question Answering Board", - "reference": "/example-boards/playground/hugging-face-question-answering.json", - "version": "" - }, - { - "title": "Hugging Face Translation Russian to English Board", - "reference": "/example-boards/playground/hugging-face-russian-english-translation.json", - "version": "" - }, - { - "title": "Hugging Face Summarization Board", - "reference": "/example-boards/playground/hugging-face-summarization.json", - "version": "" - }, - { - "title": "Hugging Face Text Classification", - "reference": "/example-boards/playground/hugging-face-text-classification.json", - "version": "" - }, - { - "title": "The Calculator Board", - "reference": "/example-boards/playground/math.json", - "version": "0.0.4" - }, - { - "title": "Nager Date Available Countries API", - "reference": "/example-boards/playground/nager.date/available-countries.json", - "version": "0.1.0" - }, - { - "title": "Nager Date Country Info API", - "reference": "/example-boards/playground/nager.date/country-info.json", - "version": "0.1.0" - }, - { - "title": "Is Today a Public Holiday", - "reference": "/example-boards/playground/nager.date/is-today-public-holiday.json", - "version": "0.1.0" - }, - { - "title": "Nager Date Long Weekend API", - "reference": "/example-boards/playground/nager.date/long-weekend.json", - "version": "0.1.0" - }, - { - "title": "Nager Date Next Public Holidays Worldwide API", - "reference": "/example-boards/playground/nager.date/next-holiday-worldwide.json", - "version": "0.1.0" - }, - { - "title": "Nager Date Next Public Holiday", - "reference": "/example-boards/playground/nager.date/next-public-holiday.json", - "version": "0.0.1" - }, - { - "title": "Nager Date Public Holidays API", - "reference": "/example-boards/playground/nager.date/public-holidays.json", - "version": "0.1.0" - }, - { - "title": "Open Alex Entity Search Results", - "reference": "/example-boards/playground/open-alex-entity-search-list.json", - "version": "0.1.0" - }, - { - "title": "OpenAI GPT-3.5-turbo", - "reference": "/example-boards/playground/openai-gpt-35-turbo.json", - "version": "0.1.0" - }, - { - "title": "OpenAI GPT-4 Turbo Vision", - "reference": "/example-boards/playground/openai-gpt-4-turbo-vision.json", - "version": "0.1.0" - }, - { - "title": "The Search Summarizer Board", - "reference": "/example-boards/playground/search-summarize.json", - "version": "0.2.0" - }, - { - "title": "The simplest LLM-based board", - "reference": "/example-boards/playground/simplest.json", - "version": "0.1.0" - }, - { - "title": "Text Generator", - "reference": "/example-boards/playground/text-generator.json", - "version": "0.1.0" - }, - { - "title": "Webcam", - "reference": "/example-boards/playground/webcam.json", - "version": "0.1.0" - }, - { - "title": "Simple chatbot (accumulating context)", - "reference": "/example-boards/playground/accumulating-context.json", - "version": "0.0.2" - }, - { - "title": "Ad Writer (variant 2)", - "reference": "/example-boards/playground/ad-writer-2.json", - "version": "0.0.2" - }, - { - "title": "Ad Writer", - "reference": "/example-boards/playground/ad-writer.json", - "version": "0.0.3" - }, - { - "title": "Agent Chain", - "reference": "/example-boards/playground/agent-chain.json", - "version": "0.0.2" - }, - { - "title": "Best of N", - "reference": "/example-boards/playground/best-of-n.json", - "version": "0.0.2" - }, - { - "title": "Board for Each", - "reference": "/example-boards/playground/board-for-each.json", - "version": "0.0.1" - }, - { - "title": "Business Review Replier Demo", - "reference": "/example-boards/playground/business-review-replier-demo.json", - "version": "0.0.1" - }, - { - "title": "Business Review Reply Generator", - "reference": "/example-boards/playground/business-review-replier.json", - "version": "0.0.1" - }, - { - "title": "Chat bot 2.0", - "reference": "/example-boards/playground/chat-bot-2.json", - "version": "0.0.1" - }, - { - "title": "Gemini Pro Generator", - "reference": "/example-boards/playground/gemini-generator.json", - "version": "0.0.2" - }, - { - "title": "Tool: Get Wiki Article", - "reference": "/example-boards/playground/get-wiki-article-tool.bgl.json", - "version": "0.0.1", - "tags": [ - "tool" - ] - }, - { - "title": "Looper Chat Testing Grounds", - "reference": "/example-boards/playground/looper-chat-test.json", - "version": "0.0.1" - }, - { - "title": "Looper Testing Grounds", - "reference": "/example-boards/playground/looper-test.json", - "version": "0.0.1" - }, - { - "title": "Object Manipulator", - "reference": "/example-boards/playground/object-manipulator.json", - "version": "0.0.1" - }, - { - "title": "Dense text summarizer (single iteration)", - "reference": "/example-boards/playground/summarize-single-iteration.json", - "version": "0.0.1" - }, - { - "title": "Dense text summarizer", - "reference": "/example-boards/playground/summarizer.json", - "version": "0.0.1" - }, - { - "title": "Specialist Testing Grounds", - "reference": "/example-boards/playground/super-worker-test.json", - "version": "0.0.1" - }, - { - "title": "Team Builder", - "reference": "/example-boards/playground/team-builder.json", - "version": "0.0.1" - }, - { - "title": "Tour Guide Writer", - "reference": "/example-boards/playground/tour-guide-writer.json", - "version": "0.0.3" - }, - { - "title": "Tool: Wiki Search", - "reference": "/example-boards/playground/wiki-search-tool.bgl.json", - "version": "0.0.1", - "tags": [ - "tool" - ] - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/examples/array-split-jsonata.bgl.json b/packages/example-boards/src/boards/examples/array-split-jsonata.bgl.json deleted file mode 100644 index 9ec73e964b2..00000000000 --- a/packages/example-boards/src/boards/examples/array-split-jsonata.bgl.json +++ /dev/null @@ -1,153 +0,0 @@ -{ - "title": "Cookbook: Split an Array with JSONata", - "description": "Splits an array of numbers using JSONata", - "version": "0.0.1", - "metadata": { - "help": { - "description": "Read the explanation", - "url": "https://breadboard-ai.github.io/breadboard/docs/guides/cookbook/#splitting-an-array" - }, - "tags": [], - "comments": [ - { - "id": "comment-d5179ae3", - "text": "Generates an array of values like `[1, 2]`", - "metadata": { - "visual": { - "x": -140, - "y": -36, - "collapsed": true - } - } - }, - { - "id": "comment-da6d6e12", - "text": "Uses [JSONata](https://jsonata.org/) to \"select into\" the array of numbers and grab the item of interest.", - "metadata": { - "visual": { - "x": 167, - "y": -139, - "collapsed": true - } - } - }, - { - "id": "comment-d234a397", - "text": "Read the explanation: [Splitting an Array](https://breadboard-ai.github.io/breadboard/docs/guides/cookbook/#splitting-an-array)", - "metadata": { - "visual": { - "x": -139, - "y": -192, - "collapsed": true - } - } - } - ] - }, - "edges": [ - { - "from": "runJavascript-ab2e7720", - "to": "jsonata-d0aa6c2b", - "out": "result", - "in": "json" - }, - { - "from": "jsonata-d0aa6c2b", - "to": "output", - "out": "result", - "in": "context" - }, - { - "from": "runJavascript-ab2e7720", - "to": "jsonata-019cb303", - "out": "result", - "in": "json" - }, - { - "from": "jsonata-019cb303", - "to": "output", - "out": "result", - "in": "property-2" - } - ], - "nodes": [ - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "number", - "title": "First Number", - "examples": [] - }, - "property-2": { - "type": "number", - "title": "Second Number", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 475, - "y": 46, - "collapsed": true - } - } - }, - { - "id": "runJavascript-ab2e7720", - "type": "runJavascript", - "metadata": { - "visual": { - "x": -145, - "y": 44, - "collapsed": true - }, - "title": "Number Generator", - "logLevel": "debug" - }, - "configuration": { - "name": "run", - "code": "const run = () => {\n return [1, 2];\n}" - } - }, - { - "id": "jsonata-d0aa6c2b", - "type": "jsonata", - "metadata": { - "visual": { - "x": 197, - "y": -37, - "collapsed": true - }, - "title": "First Number", - "logLevel": "debug" - }, - "configuration": { - "expression": "$[0]" - } - }, - { - "id": "jsonata-019cb303", - "type": "jsonata", - "metadata": { - "visual": { - "x": 188, - "y": 120, - "collapsed": true - }, - "title": "Second Number", - "logLevel": "debug" - }, - "configuration": { - "expression": "$[1]" - } - } - ] -} diff --git a/packages/example-boards/src/boards/examples/blank.ts b/packages/example-boards/src/boards/examples/blank.ts deleted file mode 100644 index 065e3feecfe..00000000000 --- a/packages/example-boards/src/boards/examples/blank.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { board, input } from "@breadboard-ai/build"; - -const text = input(); - -export default board({ - title: "Basics: Blank board", - description: "A blank board. Use it to start a new board", - version: "0.0.1", - inputs: { text }, - outputs: { text }, -}); diff --git a/packages/example-boards/src/boards/examples/google-books-api.json b/packages/example-boards/src/boards/examples/google-books-api.json deleted file mode 100644 index 377978371d3..00000000000 --- a/packages/example-boards/src/boards/examples/google-books-api.json +++ /dev/null @@ -1,145 +0,0 @@ -{ - "title": "Cookbook: Fetch Data", - "description": "Fetches data from the Google Books API using a string query", - "version": "0.0.1", - "metadata": { - "help": { - "description": "Read the explanation", - "url": "https://breadboard-ai.github.io/breadboard/docs/guides/cookbook/#fetching-data" - }, - "comments": [ - { - "id": "comment-0a7a93c1", - "text": "Encodes the user's input into the URL", - "metadata": { - "visual": { - "x": 87, - "y": -104, - "collapsed": true - } - } - }, - { - "id": "comment-3838bc8d", - "text": "Makes a request to the remote service or API", - "metadata": { - "visual": { - "x": 376, - "y": -138, - "collapsed": true - } - } - }, - { - "id": "comment-d234a397", - "text": "Read the explanation: [Fetching data](https://breadboard-ai.github.io/breadboard/docs/guides/cookbook/#fetching-data)", - "metadata": { - "visual": { - "x": -122, - "y": -192, - "collapsed": true - } - } - } - ] - }, - "edges": [ - { - "from": "urlTemplate-e919c843", - "to": "fetch-f40abdf9", - "out": "url", - "in": "url" - }, - { - "from": "fetch-f40abdf9", - "to": "output", - "out": "response", - "in": "context" - }, - { - "from": "input", - "to": "urlTemplate-e919c843", - "out": "query", - "in": "query" - } - ], - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "query": { - "type": "string", - "title": "Query", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -123, - "y": 3, - "collapsed": false - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "object", - "title": "Context", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 643, - "y": 28, - "collapsed": true - } - } - }, - { - "id": "urlTemplate-e919c843", - "type": "urlTemplate", - "metadata": { - "visual": { - "x": 88, - "y": -18, - "collapsed": false - }, - "title": "Google Books API", - "logLevel": "debug" - }, - "configuration": { - "template": "https://www.googleapis.com/books/v1/volumes?q={query}&orderBy=relevance" - } - }, - { - "id": "fetch-f40abdf9", - "type": "fetch", - "metadata": { - "visual": { - "x": 382, - "y": -47, - "collapsed": false - }, - "title": "Data Fetcher", - "logLevel": "debug" - } - } - ] -} diff --git a/packages/example-boards/src/boards/examples/hello-specialist.bgl.json b/packages/example-boards/src/boards/examples/hello-specialist.bgl.json deleted file mode 100644 index 2dadaed88a7..00000000000 --- a/packages/example-boards/src/boards/examples/hello-specialist.bgl.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "title": "Guide: Hello, Specialist", - "description": "A board demonstrating the use of a Specialist.", - "version": "0.0.1", - "metadata": { - "help": { - "description": "Read the guide", - "url": "https://breadboard-ai.github.io/breadboard/docs/getting-started/" - }, - "comments": [ - { - "id": "comment-263f335a", - "text": "This is a **Greeter** Specialist. It has a persona that tells it how to behave.", - "metadata": { - "visual": { - "x": -49, - "y": 32, - "collapsed": true - } - } - }, - { - "id": "comment-5c54e70e", - "text": "This is our board's **input**. For this board it accepts a greeting as a string.", - "metadata": { - "visual": { - "x": -188, - "y": -193, - "collapsed": true - } - } - }, - { - "id": "comment-efe8de4d", - "text": "This is our board's **output** where we see the response from our Specialist", - "metadata": { - "visual": { - "x": 91, - "y": -193, - "collapsed": true - } - } - }, - { - "id": "comment-d234a397", - "text": "Read the guide: [Getting Started](https://breadboard-ai.github.io/breadboard/docs/getting-started/)", - "metadata": { - "visual": { - "x": -45, - "y": -323, - "collapsed": true - } - } - } - ] - }, - "edges": [ - { - "from": "input", - "to": "specialist-465c8d47", - "in": "in", - "out": "context" - }, - { - "from": "specialist-465c8d47", - "to": "output", - "in": "context", - "out": "out" - } - ], - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -81.953125, - "y": -93.20703125, - "collapsed": true - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "null" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 91.046875, - "y": -93.20703125, - "collapsed": true - } - } - }, - { - "id": "specialist-465c8d47", - "type": "specialist", - "metadata": { - "visual": { - "x": -33.953125, - "y": -18.20703125, - "collapsed": true - }, - "title": "Greeter", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a cheery greeter who always responds with a fun fact." - } - ] - } - } - } - ] -} diff --git a/packages/example-boards/src/boards/examples/librarian.bgl.json b/packages/example-boards/src/boards/examples/librarian.bgl.json deleted file mode 100644 index 7800d12809e..00000000000 --- a/packages/example-boards/src/boards/examples/librarian.bgl.json +++ /dev/null @@ -1,353 +0,0 @@ -{ - "title": "Guide: My Librarian", - "version": "0.0.1", - "metadata": { - "help": { - "description": "Read the guide", - "url": "https://breadboard-ai.github.io/breadboard/docs/guides/librarian/" - }, - "comments": [ - { - "id": "comment-62f8bec6", - "text": "Comes up with a plan for a short (3-5 question) interview based on the initial topic, then runs the loop through\nall steps of the plan.", - "metadata": { - "visual": { - "x": -126, - "y": -208, - "collapsed": false - } - } - }, - { - "id": "comment-a4d85fb6", - "text": "Starts by asking\nfor the topic.", - "metadata": { - "visual": { - "x": -321.9999999999999, - "y": -146, - "collapsed": false - } - } - }, - { - "id": "comment-b9f31568", - "text": "Formulates a question based on the current step of the plan and the interview answers so far. ", - "metadata": { - "visual": { - "x": -142, - "y": 189.99999999999955, - "collapsed": false - } - } - }, - { - "id": "comment-850bcb3a", - "text": "Based on the interview results, formulates and makes 3 varying queries\nto Google Books API.", - "metadata": { - "visual": { - "x": 124, - "y": -218, - "collapsed": false - } - } - }, - { - "id": "comment-4acc26c4", - "text": "Hands control over to the user, letting the user respond to the interview question.", - "metadata": { - "visual": { - "x": 277, - "y": 152, - "collapsed": false - } - } - }, - { - "id": "comment-1b9968a5", - "text": "Summarizes the results and formats them nicely for final output.", - "metadata": { - "visual": { - "x": 368, - "y": -235, - "collapsed": false - } - } - }, - { - "id": "comment-b01c469b", - "text": "Ends by presenting recommendations.", - "metadata": { - "visual": { - "x": 504, - "y": 82, - "collapsed": false - } - } - }, - { - "id": "comment-83b726df", - "text": "📚 THE LIBRARIAN 📚\nHelps you find\nthe next book \nor your reading list.", - "metadata": { - "visual": { - "x": -302, - "y": 8.999999999999886, - "collapsed": false - } - } - }, - { - "id": "comment-edeb1a7c", - "text": "< goes back to planner", - "metadata": { - "visual": { - "x": 216, - "y": 4, - "collapsed": false - } - } - }, - { - "id": "comment-d234a397", - "text": "Read the guide: [Building a Librarian with the Agent Kit](https://breadboard-ai.github.io/breadboard/docs/guides/librarian/)", - "metadata": { - "visual": { - "x": -322, - "y": -316, - "collapsed": true - } - } - } - ], - "tags": [] - }, - "edges": [ - { - "from": "looper-b381bf13", - "to": "specialist-2551887d", - "in": "in", - "out": "loop" - }, - { - "from": "input", - "to": "looper-b381bf13", - "in": "context", - "out": "context" - }, - { - "from": "specialist-2551887d", - "to": "human-8b77a262", - "in": "context", - "out": "out" - }, - { - "from": "human-8b77a262", - "to": "looper-b381bf13", - "in": "context", - "out": "context" - }, - { - "from": "looper-b381bf13", - "to": "specialist-27a12855", - "in": "in", - "out": "done" - }, - { - "from": "specialist-27a12855", - "to": "specialist-8928cd1a", - "out": "out", - "in": "in" - }, - { - "from": "specialist-8928cd1a", - "to": "output", - "out": "out", - "in": "context" - } - ], - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]", - "description": "What book are you looking for?" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -281.9999999999998, - "y": -92, - "collapsed": false - } - } - }, - { - "id": "looper-b381bf13", - "type": "looper", - "metadata": { - "visual": { - "x": -78.99999999999989, - "y": -99, - "collapsed": false - }, - "title": "Interview Planner", - "logLevel": "debug" - }, - "configuration": { - "task": { - "role": "user", - "parts": [ - { - "text": "Based on the initial topic, come up with the themes for 3-5 question interview to collect just enough information to look for an interesting book in the library." - } - ] - } - } - }, - { - "id": "specialist-2551887d", - "type": "specialist", - "metadata": { - "visual": { - "x": -56, - "y": 120, - "collapsed": false - }, - "title": "Interviewer", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are an expert researcher, whose job it is to interview the user to collect information about the kind of book they want. Based on the theme provided and incorporating the history of the interview so far, offer a question that allows the user to easily pick or quickly type an answer." - } - ] - } - } - }, - { - "id": "specialist-27a12855", - "type": "specialist", - "metadata": { - "visual": { - "x": 149, - "y": -118, - "collapsed": false - }, - "title": "Researcher", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a librarian. Based on the information collected from the interview, formulate the queries (more than one if necessary) and call (in parallel) Google Books API to search for the right book for the user." - } - ] - }, - "tools": [ - "https://breadboard-ai.github.io/breadboard/static/boards/librarian/tool-google-books.bgl.json" - ], - "task": { - "role": "user", - "parts": [ - { - "text": "Make up to three parallel tool calls to Google Books API using different unique phrases to get the best results." - } - ] - } - } - }, - { - "id": "human-8b77a262", - "type": "human", - "metadata": { - "visual": { - "x": 179, - "y": 79.99999999999977, - "collapsed": false - }, - "title": "Interviewee", - "logLevel": "debug" - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "null" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 472, - "y": 12.999999999999886, - "collapsed": false - } - } - }, - { - "id": "specialist-8928cd1a", - "type": "specialist", - "metadata": { - "visual": { - "x": 392, - "y": -157.99999999999994, - "collapsed": false - }, - "title": "Summarizer", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are an expert librarian. You take the raw book search results from multiple queries and the interview information that was collected, and come up with a list of book recommendations." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Come up with a list of 5-7 recommendations. Reply in markdown, making book titles hyperlinks to the book's canonicalVolumeLink and use smallThumbnail to display the book's thumbnail. " - } - ] - } - } - } - ], - "description": "A simple agent that helps me find interesting books." -} diff --git a/packages/example-boards/src/boards/examples/novel-generator.bgl.json b/packages/example-boards/src/boards/examples/novel-generator.bgl.json deleted file mode 100644 index de14a95c530..00000000000 --- a/packages/example-boards/src/boards/examples/novel-generator.bgl.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "title": "Guide: Novel Generator", - "description": "Generates a novel based on an idea.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": [ - "llm-content" - ] - }, - "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 100.71093750000003, - "y": -107.34375000000006, - "collapsed": true - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": [ - "llm-content" - ] - }, - "default": "null" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 790.7109375000001, - "y": -105.34375000000006, - "collapsed": true - } - } - }, - { - "id": "specialist-9c080a8c", - "type": "specialist", - "metadata": { - "visual": { - "x": 298.99999999999994, - "y": -107.99999999999994, - "collapsed": true - }, - "title": "Outliner", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a professional novel outliner." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Call the novel outliner tool with the prompt." - } - ] - }, - "tools": [ - "https://breadboard-ai.github.io/breadboard/static/boards/novel-generator/tool-novel-outliner.bgl.json" - ] - } - }, - { - "id": "specialist-8efe9743", - "type": "specialist", - "metadata": { - "visual": { - "x": 521.7109375000001, - "y": -108.34374999999983, - "collapsed": true - }, - "title": "Developer", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a professional developer of novels." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Call the novel developer tool with the prompt." - } - ] - }, - "tools": [ - "https://breadboard-ai.github.io/breadboard/static/boards/novel-generator/tool-novel-developer.bgl.json" - ] - } - } - ], - "edges": [ - { - "from": "input", - "to": "specialist-9c080a8c", - "in": "in", - "out": "context" - }, - { - "from": "specialist-8efe9743", - "to": "output", - "in": "context", - "out": "out" - }, - { - "from": "specialist-9c080a8c", - "to": "specialist-8efe9743", - "in": "in", - "out": "out" - } - ], - "metadata": { - "comments": [ - { - "id": "comment-d234a397", - "text": "Read the guide: [Building a Novel Generator with the Agent Kit](https://breadboard-ai.github.io/breadboard/docs/guides/novel-generator/)", - "metadata": { - "visual": { - "x": 119, - "y": -265.9999999999999, - "collapsed": true - } - } - } - ], - "tags": [] - } -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/examples/rhyme-of-the-day.bgl.json b/packages/example-boards/src/boards/examples/rhyme-of-the-day.bgl.json deleted file mode 100644 index 6013934656a..00000000000 --- a/packages/example-boards/src/boards/examples/rhyme-of-the-day.bgl.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "title": "Guide: Rhyme of the Day", - "description": "Creates a poem based on today's date", - "version": "0.0.1", - "metadata": { - "help": { - "description": "Read the guide", - "url": "https://breadboard-ai.github.io/breadboard/docs/guides/first-tool/" - }, - "comments": [ - { - "id": "comment-d234a397", - "text": "Read the guide: [Building our First Tool](https://breadboard-ai.github.io/breadboard/docs/guides/first-tool/)", - "metadata": { - "visual": { - "x": 296, - "y": -111, - "collapsed": true - } - } - } - ] - }, - "edges": [ - { - "from": "input", - "to": "specialist-aa651c47", - "out": "context", - "in": "in" - }, - { - "from": "specialist-aa651c47", - "to": "specialist-9eac4e83", - "out": "out", - "in": "in" - }, - { - "from": "specialist-9eac4e83", - "to": "output", - "out": "out", - "in": "context" - } - ], - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 0, - "y": 0, - "collapsed": true - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": ["llm-content"] - }, - "default": "null" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 695, - "y": 0, - "collapsed": true - } - } - }, - { - "id": "specialist-9eac4e83", - "type": "specialist", - "metadata": { - "visual": { - "x": 448, - "y": 0, - "collapsed": true - }, - "title": "Poet", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You write wonderful poems that incorporate today's date." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Write a poem for the user in the style requested, using today's date. If the user doesn't provide a style, feel free to choose your own." - } - ] - } - } - }, - { - "id": "specialist-aa651c47", - "type": "specialist", - "metadata": { - "visual": { - "x": 173, - "y": 0, - "collapsed": true - }, - "title": "Date Retriever", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You invoke tools to answer queries." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Use the tool to get today's date." - } - ] - }, - "tools": [ - "https://breadboard-ai.github.io/breadboard/static/boards/first-tool/tool-today-s-date.bgl.json" - ] - } - } - ] -} diff --git a/packages/example-boards/src/boards/examples/social-media-post-creator.bgl.json b/packages/example-boards/src/boards/examples/social-media-post-creator.bgl.json deleted file mode 100644 index 8f917f0199c..00000000000 --- a/packages/example-boards/src/boards/examples/social-media-post-creator.bgl.json +++ /dev/null @@ -1,237 +0,0 @@ -{ - "title": "Guide: Social Media Post Creator", - "description": "Contains board up through caption creation", - "version": "0.0.1", - "nodes": [ - { - "id": "human-a7ffc3c9", - "type": "human", - "metadata": { - "visual": { - "x": 876, - "y": 302, - "collapsed": false - }, - "title": "Interviewee", - "logLevel": "debug", - "description": "user participating in the chat" - } - }, - { - "id": "specialist-1b71b8b7", - "type": "specialist", - "metadata": { - "visual": { - "x": 1048, - "y": 106, - "collapsed": false - }, - "title": "Interviewer", - "description": "get the business name and location", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are an expert interviewer, whose job it is to interview the user to find out what their social media post is about and theirs goals for it are. Based on the theme provided and incorporating the history of the interview so far, ask ONE question that allows the user to easily and quickly type an answer. You only need to get one basic answer from the user." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Ask just ONE question that includes what this social media post is about and its main goal. You only need to elicit ONE answer. Do so in a friendly and casual manner." - } - ] - } - } - }, - { - "id": "looper-03c40c9b", - "type": "looper", - "metadata": { - "visual": { - "x": 773, - "y": 86, - "collapsed": false - }, - "title": "Interview Planner", - "logLevel": "debug", - "description": "Sets up the basics for the interview conversation loop" - }, - "configuration": { - "task": { - "role": "user", - "parts": [ - { - "text": "Based on the initial topic, come up with ONE question to collect just enough information from the user about the social media post's topic and goals. You only need to get one answer from the user." - } - ] - } - } - }, - { - "id": "output-11fb8604", - "type": "output", - "metadata": { - "visual": { - "x": 1328, - "y": 102, - "collapsed": false - }, - "title": "output", - "logLevel": "debug" - }, - "configuration": { - "schema": { - "properties": { - "property-1": { - "type": "object", - "title": "out", - "examples": [], - "behavior": ["llm-content"], - "default": "null" - } - }, - "type": "object", - "required": [] - } - } - }, - { - "id": "input-78f58945", - "type": "input", - "metadata": { - "visual": { - "x": 431, - "y": 85, - "collapsed": false - }, - "title": "Get business name and location", - "description": "Asks for the business name and location", - "logLevel": "debug" - }, - "configuration": { - "schema": { - "properties": { - "content": { - "type": "object", - "title": "Business Name", - "examples": [], - "behavior": ["llm-content"], - "default": "{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}" - }, - "property-2": { - "type": "object", - "behavior": ["llm-content"], - "title": "Business Location (city and state)", - "examples": [], - "default": "{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}" - } - }, - "type": "object", - "required": [] - } - } - }, - { - "id": "specialist-1edddf49", - "type": "specialist", - "metadata": { - "title": "Caption creator", - "logLevel": "debug", - "visual": { - "x": 1046, - "y": -16, - "collapsed": false - } - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are an expert social media caption creator. You take user input and the\nsummary of the business search results to create an caption such as those\nfound on Instagram that fit this company's profile and client needs. As an\nexpert, you will decide on the text, hashtags and emojis needed for the caption.\n\n" - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Create a social media caption based on the user's business and post details and your expert knowledge of the business world and\nsocial media." - } - ] - }, - "tools": [] - } - } - ], - "edges": [ - { - "from": "input-78f58945", - "to": "looper-03c40c9b", - "out": "content", - "in": "context" - }, - { - "from": "input-78f58945", - "to": "looper-03c40c9b", - "out": "property-2", - "in": "context" - }, - { - "from": "looper-03c40c9b", - "to": "specialist-1b71b8b7", - "out": "loop", - "in": "in" - }, - { - "from": "specialist-1b71b8b7", - "to": "human-a7ffc3c9", - "out": "out", - "in": "context" - }, - { - "from": "human-a7ffc3c9", - "to": "looper-03c40c9b", - "out": "context", - "in": "context" - }, - { - "from": "looper-03c40c9b", - "to": "specialist-1edddf49", - "out": "done", - "in": "in" - }, - { - "from": "specialist-1edddf49", - "to": "output-11fb8604", - "out": "out", - "in": "property-1" - } - ], - "metadata": { - "help": { - "description": "Read the guide", - "url": "https://breadboard-ai.github.io/breadboard/docs/guides/social-post/" - }, - "comments": [ - { - "id": "comment-d234a397", - "text": "Read the guide: [Building a Social Media Post Creator with the Agent Kit](https://breadboard-ai.github.io/breadboard/docs/guides/social-post/)", - "metadata": { - "visual": { - "x": 431, - "y": -64, - "collapsed": true - } - } - } - ], - "tags": [] - } -} diff --git a/packages/example-boards/src/boards/examples/tool-novel-developer.bgl.json b/packages/example-boards/src/boards/examples/tool-novel-developer.bgl.json deleted file mode 100644 index 310d1b1f099..00000000000 --- a/packages/example-boards/src/boards/examples/tool-novel-developer.bgl.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "title": "Tool: Novel Developer", - "description": "Develops a novel based on an outline.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": [ - "llm-content" - ] - }, - "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 202.05468749999983, - "y": -28.183593749999943, - "collapsed": true - } - } - }, - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": [ - "llm-content" - ] - }, - "default": "null" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 967.04248046875, - "y": -28.34941482543951, - "collapsed": true - } - } - }, - { - "id": "looper-020e2fb5", - "type": "looper", - "metadata": { - "visual": { - "x": 433.0546875, - "y": -29.183593749999773, - "collapsed": true - }, - "title": "Literary Agent", - "logLevel": "debug" - }, - "configuration": { - "task": { - "role": "user", - "parts": [ - { - "text": "Chapter-by-chapter, generate a draft for the novel. Use single-paragraph micro chapters for quick iterations." - } - ] - } - } - }, - { - "id": "specialist-3df0b1c6", - "type": "specialist", - "metadata": { - "visual": { - "x": 672.0546874999999, - "y": 278.8164062500002, - "collapsed": true - }, - "title": "Writer (revise)", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a professional novelist." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Revise the chapter following the suggestions." - } - ] - } - } - }, - { - "id": "specialist-bbb00f97", - "type": "specialist", - "metadata": { - "visual": { - "x": 710.0424804687501, - "y": -28.34941482543951, - "collapsed": true - }, - "title": "Publisher", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a professional book publisher." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Format the manuscript into a novel, ready for digital consumption. Omit any scribbles and annotations not intended for the reading public." - } - ] - } - } - }, - { - "id": "specialist-47601c04", - "type": "specialist", - "metadata": { - "visual": { - "x": 458.0546874999998, - "y": 278.8164062500002, - "collapsed": true - }, - "title": "Editor", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a professional line editor of novels." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Give feedback on the chapter. Include 3 detailed suggestions to improve clarity, flow, and impact." - } - ] - } - } - }, - { - "id": "specialist-88d52299", - "type": "specialist", - "metadata": { - "visual": { - "x": 243.05468749999994, - "y": 277.81640625, - "collapsed": true - }, - "title": "Writer (draft)", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a professional novelist." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "" - } - ] - } - } - } - ], - "edges": [ - { - "from": "looper-020e2fb5", - "to": "specialist-bbb00f97", - "in": "in", - "out": "done" - }, - { - "from": "specialist-88d52299", - "to": "specialist-47601c04", - "in": "in", - "out": "out" - }, - { - "from": "specialist-47601c04", - "to": "specialist-3df0b1c6", - "in": "in", - "out": "out" - }, - { - "from": "looper-020e2fb5", - "to": "specialist-88d52299", - "in": "in", - "out": "loop" - }, - { - "from": "specialist-3df0b1c6", - "to": "looper-020e2fb5", - "in": "context", - "out": "out" - }, - { - "from": "input", - "to": "looper-020e2fb5", - "in": "context", - "out": "context" - }, - { - "from": "specialist-bbb00f97", - "to": "output", - "in": "context", - "out": "out" - } - ], - "metadata": { - "help": { - "description": "Read the guide", - "url": "https://breadboard-ai.github.io/breadboard/docs/guides/novel-generator/" - }, - "comments": [ - { - "id": "comment-7f904f21", - "text": "Develops the novel chapter by chapter", - "metadata": { - "visual": { - "x": 436.0424804687499, - "y": -116.34941482543957, - "collapsed": true - } - } - }, - { - "id": "comment-d234a397", - "text": "Read the guide: [Building a Novel Generator with the Agent Kit](https://breadboard-ai.github.io/breadboard/docs/guides/novel-generator/)", - "metadata": { - "visual": { - "x": 203.9999999999999, - "y": -213, - "collapsed": true - } - } - } - ], - "tags": [ - "tool" - ] - } -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/examples/tool-novel-outliner.bgl.json b/packages/example-boards/src/boards/examples/tool-novel-outliner.bgl.json deleted file mode 100644 index 04d1528bd81..00000000000 --- a/packages/example-boards/src/boards/examples/tool-novel-outliner.bgl.json +++ /dev/null @@ -1,448 +0,0 @@ -{ - "title": "Tool: Novel Outliner", - "description": "Outlines a novel outline based on an idea.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input-fc498fdd", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": [ - "llm-content" - ] - }, - "default": "[{\"role\":\"user\",\"parts\":[{\"text\":\"\"}]}]" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 163.29296875, - "y": -312.60546875, - "collapsed": true - }, - "title": "Input", - "logLevel": "debug" - } - }, - { - "type": "output", - "id": "output-0760951b", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "array", - "title": "Context", - "examples": [], - "items": { - "type": "object", - "behavior": [ - "llm-content" - ] - }, - "default": "null" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 1523.2929687500002, - "y": -310.6054687500002, - "collapsed": true - }, - "title": "Result", - "logLevel": "debug" - } - }, - { - "id": "specialist-c246f084", - "type": "specialist", - "metadata": { - "visual": { - "x": 329.18855729498694, - "y": -311.6449007811074, - "collapsed": true - }, - "title": "Author", - "description": "Description", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a professional novelist." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Write a novel outline inspired by the given information. Structure it in twelve chapters." - } - ] - } - } - }, - { - "id": "human-ce6dd4f9", - "type": "human", - "metadata": { - "visual": { - "x": 1289.29296875, - "y": -310.6054687500002, - "collapsed": true - }, - "title": "Patron", - "logLevel": "debug", - "description": "Choice of outline" - }, - "configuration": { - "title": "User", - "description": "A request or response" - } - }, - { - "id": "specialist-f974170a", - "type": "specialist", - "metadata": { - "visual": { - "x": 594.29296875, - "y": -453.6054687500001, - "collapsed": true - }, - "title": "Friend (encouraging)", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a trusted friend and writing fellow of the author. Your tone is encouraging. " - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Give feedback on the novel outline. Include three suggestions to improve readability and engagement." - } - ] - } - } - }, - { - "id": "specialist-57b87a2d", - "type": "specialist", - "metadata": { - "visual": { - "x": 586.29296875, - "y": -308.6054687500002, - "collapsed": true - }, - "title": "Friend (skeptical)", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a trusted friend and writing fellow of the author. Your tone is skeptical." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Give feedback on the novel outline. Include three suggestions to improve readability and engagement." - } - ] - } - } - }, - { - "id": "specialist-3abe2788", - "type": "specialist", - "metadata": { - "visual": { - "x": 590.2929687499999, - "y": -183.60546875, - "collapsed": true - }, - "title": "Friend (neutral)", - "logLevel": "debug" - }, - "configuration": { - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a trusted friend and writing fellow of the author. Your tone is neutral." - } - ] - }, - "task": { - "role": "user", - "parts": [ - { - "text": "Give feedback on the novel outline. Include three suggestions to improve readability and engagement." - } - ] - } - } - }, - { - "id": "joiner-ca15c787", - "type": "joiner", - "metadata": { - "visual": { - "x": 1086.29296875, - "y": -310.6054687500002, - "collapsed": true - }, - "title": "SxS", - "logLevel": "debug" - }, - "configuration": {} - }, - { - "id": "specialist-7b5d80e7", - "type": "specialist", - "metadata": { - "visual": { - "x": 835.29296875, - "y": -452.60546875000006, - "collapsed": true - }, - "title": "Author", - "logLevel": "debug" - }, - "configuration": { - "task": { - "role": "user", - "parts": [ - { - "text": "Revise the outline following the suggestions. Prefix the result with \"Novel Outline 1\"." - } - ] - }, - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a professional novelist." - } - ] - } - } - }, - { - "id": "specialist-b98b8244", - "type": "specialist", - "metadata": { - "visual": { - "x": 827.2929687500001, - "y": -308.6054687500001, - "collapsed": true - }, - "title": "Author", - "logLevel": "debug" - }, - "configuration": { - "task": { - "role": "user", - "parts": [ - { - "text": "Revise the outline following the suggestions. Prefix the result with \"Novel Outline 2\"." - } - ] - }, - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a professional novelist." - } - ] - } - } - }, - { - "id": "specialist-374e4f2a", - "type": "specialist", - "metadata": { - "visual": { - "x": 826.29296875, - "y": -183.60546875, - "collapsed": true - }, - "title": "Author", - "logLevel": "debug" - }, - "configuration": { - "task": { - "role": "user", - "parts": [ - { - "text": "Revise the outline following the suggestions. Prefix the result with \"Novel Outline 3\"." - } - ] - }, - "persona": { - "role": "user", - "parts": [ - { - "text": "You are a professional novelist." - } - ] - } - } - } - ], - "edges": [ - { - "from": "input-fc498fdd", - "to": "specialist-c246f084", - "in": "in", - "out": "context" - }, - { - "from": "specialist-c246f084", - "to": "specialist-57b87a2d", - "in": "in", - "out": "out" - }, - { - "from": "specialist-f974170a", - "to": "specialist-7b5d80e7", - "in": "in", - "out": "out" - }, - { - "from": "specialist-57b87a2d", - "to": "specialist-b98b8244", - "in": "in", - "out": "out" - }, - { - "from": "specialist-3abe2788", - "to": "specialist-374e4f2a", - "in": "in", - "out": "out" - }, - { - "from": "human-ce6dd4f9", - "to": "output-0760951b", - "in": "context", - "out": "context" - }, - { - "from": "joiner-ca15c787", - "to": "human-ce6dd4f9", - "in": "context", - "out": "context" - }, - { - "from": "specialist-c246f084", - "to": "specialist-f974170a", - "in": "in", - "out": "out" - }, - { - "from": "specialist-c246f084", - "to": "specialist-3abe2788", - "in": "in", - "out": "out" - }, - { - "from": "specialist-7b5d80e7", - "to": "joiner-ca15c787", - "in": "outline-1", - "out": "out" - }, - { - "from": "specialist-b98b8244", - "to": "joiner-ca15c787", - "in": "outline-2", - "out": "out" - }, - { - "from": "specialist-374e4f2a", - "to": "joiner-ca15c787", - "in": "outline-3", - "out": "out" - } - ], - "metadata": { - "comments": [ - { - "id": "comment-975f58ba", - "text": "Writes initial draft", - "metadata": { - "visual": { - "x": 255.29296875, - "y": -389.60546875000017, - "collapsed": true - } - } - }, - { - "id": "comment-da5e644c", - "text": "Generates 3 parallel revisions", - "metadata": { - "visual": { - "x": 695.2929687499999, - "y": -562.60546875, - "collapsed": true - } - } - }, - { - "id": "comment-f027ed0f", - "text": "Offers choice", - "metadata": { - "visual": { - "x": 1307.29296875, - "y": -398.6054687500001, - "collapsed": true - } - } - }, - { - "id": "comment-d234a397", - "text": "Read the guide: [Building a Novel Generator with the Agent Kit](https://breadboard-ai.github.io/breadboard/docs/guides/novel-generator/)", - "metadata": { - "visual": { - "x": 171, - "y": -563, - "collapsed": true - } - } - } - ], - "tags": [ - "tool" - ] - } -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/examples/tool-todays-date.bgl.json b/packages/example-boards/src/boards/examples/tool-todays-date.bgl.json deleted file mode 100644 index 5828d2d8c25..00000000000 --- a/packages/example-boards/src/boards/examples/tool-todays-date.bgl.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "title": "Tool: Today's Date", - "description": "Returns the exact date and time in the current timezone.", - "version": "0.0.1", - "metadata": { - "help": { - "description": "Read the guide", - "url": "https://breadboard-ai.github.io/breadboard/docs/guides/first-tool/" - }, - "tags": ["tool"], - "comments": [ - { - "id": "comment-d234a397", - "text": "Read the guide: [Building our First Tool](https://breadboard-ai.github.io/breadboard/docs/guides/first-tool/)", - "metadata": { - "visual": { - "x": 16, - "y": -107, - "collapsed": true - } - } - } - ] - }, - "edges": [ - { - "from": "runJavascript-7ce6f2ea", - "to": "output", - "out": "result", - "in": "context" - } - ], - "nodes": [ - { - "type": "output", - "id": "output", - "configuration": { - "schema": { - "properties": { - "context": { - "type": "string", - "title": "Context", - "examples": [] - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": 173, - "y": 0, - "collapsed": true - } - } - }, - { - "id": "runJavascript-7ce6f2ea", - "type": "runJavascript", - "metadata": { - "visual": { - "x": -50, - "y": 0.9999999999998863, - "collapsed": true - }, - "title": "Date Retriever", - "logLevel": "debug" - }, - "configuration": { - "name": "run", - "code": "const run = () => new Date().toString();" - } - } - ] -} diff --git a/packages/example-boards/src/boards/playground/accumulating-context-python.py b/packages/example-boards/src/boards/playground/accumulating-context-python.py deleted file mode 100644 index 9b7277dd729..00000000000 --- a/packages/example-boards/src/boards/playground/accumulating-context-python.py +++ /dev/null @@ -1,48 +0,0 @@ - -from breadboard_python.main import Board, Field, SchemaObject, List, AttrDict -import json -from typing import Optional, Union - -from breadboard_python.import_node import require -Core = require("@google-labs/core-kit") -Templates = require("@google-labs/template-kit") - -class InputSchema(SchemaObject): - text: str = Field(description="User: type here to chat with the assistant") - generator: str = Field("text-generator.json", description="Generator: Text generator to use") - -class OutputSchema(SchemaObject): - text: str = Field(title="Assistant", description="Assistant: Assistant's response in the conversation with the user", required=True) - - -class AccumulatingContext(Board[InputSchema, OutputSchema]): - title = "Accumulating Context (Python)" - description = 'An example of a board that implements a multi-turn experience: a very simple chat bot that accumulates context of the conversations. Tell it "I am hungry" or something like this and then give simple replies, like "bbq". It should be able to infer what you\'re asking for based on the conversation context. All replies are pure hallucinations, but should give you a sense of how a Breadboard API endpoint for a board with cycles looks like.' - version = "0.0.2" - - type = "accumulating-context" - - def describe(self, input, output): - self.prompt = Templates.promptTemplate( - id="assistant", - template="This is a conversation between a friendly assistant and their user. You are the assistant and your job is to try to be helpful, empathetic, and fun.\n{{context}}\n\n== Current Conversation\nuser: {{question}}\nassistant:", - context="", - ) - self.conversationMemory = Core.append( - accumulator="\n== Conversation History", - ) - - self.prompt(question=input.text) - self.conversationMemory(user=input.text) - self.conversationMemory(accumulator=self.conversationMemory.accumulator) - self.prompt(context=self.conversationMemory.accumulator) - generator = Core.invoke(id="generator", path=input.generator, text=self.prompt.prompt) - self.conversationMemory(assistant=generator.text) - output(text=generator.text) - input(output) - -if __name__ == "__main__": - import sys - a = AccumulatingContext() - with open(sys.argv[1], "w") as f: - json.dump(a, f, indent=2) diff --git a/packages/example-boards/src/boards/playground/accumulating-context.json b/packages/example-boards/src/boards/playground/accumulating-context.json deleted file mode 100644 index 47d6ad53193..00000000000 --- a/packages/example-boards/src/boards/playground/accumulating-context.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "title": "Simple chatbot (accumulating context)", - "description": "An example of a board that implements a multi-turn experience: a very simple chat bot that accumulates context of the conversations. Tell it \"I am hungry\" or something like this and then give simple replies, like \"bbq\". It should be able to infer what you're asking for based on the conversation context. All replies are pure hallucinations, but should give you a sense of how a Breadboard API endpoint for a board with cycles looks like.", - "version": "0.0.2", - "edges": [ - { - "from": "append-2", - "to": "append-2", - "out": "accumulator", - "in": "accumulator" - }, - { - "from": "append-2", - "to": "assistant", - "out": "accumulator", - "in": "context" - }, - { - "from": "assistant", - "to": "generator", - "out": "prompt", - "in": "text" - }, - { - "from": "generator", - "to": "append-2", - "out": "text", - "in": "assistant" - }, - { - "from": "generator", - "to": "output-3", - "out": "text", - "in": "text" - }, - { - "from": "output-3", - "to": "userRequest", - "out": "", - "in": "" - }, - { - "from": "parameters", - "to": "generator", - "out": "generator", - "in": "$board", - "constant": true - }, - { - "from": "parameters", - "to": "userRequest", - "out": "", - "in": "" - }, - { - "from": "userRequest", - "to": "append-2", - "out": "text", - "in": "user" - }, - { - "from": "userRequest", - "to": "assistant", - "out": "text", - "in": "question" - } - ], - "nodes": [ - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "generator": { - "type": "string", - "title": "Generator", - "description": "Text generator to use", - "default": "text-generator.json" - } - }, - "additionalProperties": false - } - } - }, - { - "id": "userRequest", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "User", - "description": "Type here to chat with the assistant" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - } - } - }, - { - "id": "output-3", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "text": { - "type": "string", - "title": "Assistant", - "description": "Assistant's response in the conversation with the user" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - } - } - }, - { - "id": "append-2", - "type": "append", - "configuration": { - "accumulator": "\n== Conversation History" - } - }, - { - "id": "assistant", - "type": "promptTemplate", - "configuration": { - "context": "", - "template": "This is a conversation between a friendly assistant and their user. You are the assistant and your job is to try to be helpful, empathetic, and fun.\n{{context}}\n\n== Current Conversation\nuser: {{question}}\nassistant:" - } - }, - { - "id": "generator", - "type": "invoke", - "configuration": {} - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/ad-writer-2.json b/packages/example-boards/src/boards/playground/ad-writer-2.json deleted file mode 100644 index 5637536c6ef..00000000000 --- a/packages/example-boards/src/boards/playground/ad-writer-2.json +++ /dev/null @@ -1,1167 +0,0 @@ -{ - "title": "Ad Writer (variant 2)", - "description": "An example of chain of agents working on writing an ad", - "version": "0.0.2", - "edges": [ - { - "from": "fn-5", - "to": "structuredWorker-6", - "out": "prompt", - "in": "instruction" - }, - { - "from": "fn-9", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "input-1", - "to": "structuredWorker-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - }, - { - "from": "repeater-8", - "to": "fn-9", - "out": "context", - "in": "context" - }, - { - "from": "repeater-8", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-3", - "to": "fn-5", - "out": "json", - "in": "json" - }, - { - "from": "structuredWorker-4", - "to": "structuredWorker-6", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-6", - "to": "structuredWorker-7", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-7", - "to": "repeater-8", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Ad specs", - "default": "[]", - "examples": [ - "{\"role\":\"user\",\"parts\":[{\"text\":\"Write an ad for Breadboard. The ad must incorporate the following key messages: \\n- Breadboard for Developers\\n- Play and experiment with AI Patterns\\n- Prototype quickly\\n- Use with Gemini APIs \\n- Integrate AI Into Your Project\\n- Create graphs with prompts\\n- Accessible AI for Developers\"}]}" - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - }, - "required": [ - "context" - ] - } - } - }, - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "context", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "json": { - "type": "string", - "title": "json" - } - } - } - } - }, - { - "id": "fn-5", - "type": "runJavascript", - "configuration": { - "code": "const fn_5 = ({json})=>{const{prompt}=json;return{prompt}};", - "name": "fn_5", - "raw": true - }, - "metadata": { - "title": "Prompt Extractor" - } - }, - { - "id": "fn-9", - "type": "runJavascript", - "configuration": { - "code": "const fn_9 = ({context})=>{const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);return{json}};", - "name": "fn_9", - "raw": true - }, - "metadata": { - "title": "JSON Extractor" - } - }, - { - "id": "repeater-8", - "type": "repeater", - "configuration": { - "max": 4, - "worker": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "structuredWorker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "fn-3", - "to": "structuredWorker-4", - "out": "warning", - "in": "instruction" - }, - { - "from": "fn-3", - "to": "output-5", - "out": "context", - "in": "exit" - }, - { - "from": "input-1", - "to": "fn-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "context" - } - } - } - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Shortener" - } - }, - { - "id": "fn-3", - "type": "runJavascript", - "configuration": { - "code": "const fn_3 = ({context})=>{const list=context||[];const last=list[list.length-1];const json=JSON.parse(last.parts.text);const{adCampaign}=json;const warning=[`You are a brilliant copy editor who is famous brevity, making ads in the ad campaign fit into the character limits while retaining their meaning and impact. Given the ad, follow instructions below:`];for(const headline of adCampaign.headlines){if(headline.length>30){warning.push(`The headline \"${headline}\" is ${headline.length} characters long, but needs to be 30 characters. Shorten it.`)}}for(const description of adCampaign.descriptions){if(description.length>90){warning.push(`The description \"${description}\" is ${description.length} characters long, but needs to be 90 characters. Shorten it.`)}}if(warning.length>1){return{warning:warning.join(\"\\n\\n\")}}return{context}};", - "name": "fn_3", - "raw": true - }, - "metadata": { - "title": "Character Limit Checker" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context", - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"the universe within us\"\n }\n ]\n }\n]" - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - }, - "required": [ - "context" - ] - } - } - }, - { - "id": "output-5", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "exit": { - "type": "string", - "title": "exit" - } - } - } - }, - "metadata": { - "title": "Successful exit" - } - } - ], - "graphs": {} - } - } - }, - "metadata": { - "title": "Ad refinery" - } - }, - { - "id": "structuredWorker-3", - "type": "structuredWorker", - "configuration": { - "instruction": "Using the audience information in the search engine marketing overview, create a prompt for a bot who will pretend to be the target audience for the ad. The prompt needs to incorporate the sense of skepticism and weariness of ads, yet willingness to provide constructive feedback. The prompt needs to be in the form of:\n \n \"You are [persona]. You are [list of traits].\"", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the bot" - } - } - } - }, - "metadata": { - "title": "Customer Prompt Maker", - "description": "Conjuring up a persona to represent a customer", - "logLevel": "info" - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "instruction": "Write an ad campaign (up to 15 headlines and and 4 descriptions) and that transforms the search engine marketing overview into a compelling, engaging ad.", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Writer" - } - }, - { - "id": "structuredWorker-6", - "type": "structuredWorker", - "configuration": { - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "requirement": { - "type": "string", - "description": "the requirement" - }, - "justification": { - "type": "string", - "description": "reasoning behind including this requirement" - } - } - } - } - } - } - }, - "metadata": { - "title": "Customer" - } - }, - { - "id": "structuredWorker-7", - "type": "structuredWorker", - "configuration": { - "instruction": "Given the customer critique, update the ad campaign. Make sure to conform to the requirements in the Search Engine Marketing document. Remove any uses of the word \"free\".", - "schema": { - "type": "object", - "properties": { - "adCampaign": { - "type": "object", - "description": "the ad campaign", - "properties": { - "headlines": { - "type": "array", - "items": { - "type": "string", - "description": "an ad headline (30 character limit, up to 15 headlines)" - } - }, - "descriptions": { - "type": "array", - "items": { - "type": "string", - "description": "the description (90 character limit, up to 4 descriptions)" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Editor" - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/ad-writer.json b/packages/example-boards/src/boards/playground/ad-writer.json deleted file mode 100644 index 3e0e4f43620..00000000000 --- a/packages/example-boards/src/boards/playground/ad-writer.json +++ /dev/null @@ -1,495 +0,0 @@ -{ - "title": "Ad Writer", - "description": "An example of chain of agents working on writing an ad", - "version": "0.0.3", - "edges": [ - { - "from": "input-1", - "to": "structuredWorker-3", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-10", - "to": "structuredWorker-11", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-11", - "to": "output-2", - "out": "*", - "in": "" - }, - { - "from": "structuredWorker-3", - "to": "structuredWorker-4", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-4", - "to": "structuredWorker-5", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-5", - "to": "structuredWorker-6", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-6", - "to": "structuredWorker-7", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-7", - "to": "structuredWorker-8", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-8", - "to": "structuredWorker-9", - "out": "context", - "in": "context" - }, - { - "from": "structuredWorker-9", - "to": "structuredWorker-10", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Ad specs", - "default": "[]", - "examples": [ - "{\"role\":\"user\",\"parts\":[{\"text\":\"This ad is for my lawn care company that will fit into an inch of newspaper copy. It's called \\\"Max's Lawn Care\\\" and it should use the slogan \\\"I care about your lawn.\\\" Emphasize the folksiness of it being a local, sole proprietorship that I started after graduating from high school.\"}]}" - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "format": "multiline" - } - }, - "required": [ - "context" - ] - } - } - }, - { - "id": "output-2", - "type": "output", - "configuration": {} - }, - { - "id": "structuredWorker-10", - "type": "structuredWorker", - "configuration": { - "instruction": "Given the list of requirements assess how well the newest response conforms to the requirements.", - "schema": { - "type": "object", - "properties": { - "assessment": { - "type": "array", - "items": { - "type": "object", - "properties": { - "summary": { - "type": "string", - "description": "summary of an point in the assessment" - }, - "details": { - "type": "string", - "description": "reasoning behind the point in an assessment" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Evaluator" - } - }, - { - "id": "structuredWorker-11", - "type": "structuredWorker", - "configuration": { - "instruction": "You are a Google Ads Professional. Write the ad copy that satisfies the requirements and is improved based on the assessment", - "schema": { - "type": "object", - "properties": { - "ad": { - "type": "string", - "description": "the ad copy" - } - } - } - }, - "metadata": { - "title": "Ad Editor" - } - }, - { - "id": "structuredWorker-3", - "type": "structuredWorker", - "configuration": { - "instruction": "Given the following specs, extract requirements for writing an ad copy", - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "string", - "description": "a prompt requirement" - } - } - } - } - }, - "metadata": { - "title": "Requirements Extractor" - } - }, - { - "id": "structuredWorker-4", - "type": "structuredWorker", - "configuration": { - "instruction": "Write ad copy that conforms to the requirements above", - "schema": { - "type": "object", - "properties": { - "ad": { - "type": "string", - "description": "the ad copy" - } - } - } - }, - "metadata": { - "title": "Ad Writer" - } - }, - { - "id": "structuredWorker-5", - "type": "structuredWorker", - "configuration": { - "instruction": "Imagine you are a customer. You are a middle-aged homeowner from rural Midwest. You are overrun with ads and are weary of being scammed. You just want to work with someone local and trustworty. Review this and offer three improvements that would increase the likelihood of you trusting the ad.", - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "string", - "description": "a prompt requirement" - } - } - } - } - }, - "metadata": { - "title": "Customer" - } - }, - { - "id": "structuredWorker-6", - "type": "structuredWorker", - "configuration": { - "instruction": "Incorporate all feedback above into new, improved requirements", - "schema": { - "type": "object", - "properties": { - "requirements": { - "type": "array", - "items": { - "type": "string", - "description": "a prompt requirement" - } - } - } - } - }, - "metadata": { - "title": "Requirements Extractor" - } - }, - { - "id": "structuredWorker-7", - "type": "structuredWorker", - "configuration": { - "instruction": "Write ad copy that conforms to the specified requirements", - "schema": { - "type": "object", - "properties": { - "ad": { - "type": "string", - "description": "the ad copy" - } - } - } - }, - "metadata": { - "title": "Ad Writer" - } - }, - { - "id": "structuredWorker-8", - "type": "structuredWorker", - "configuration": { - "instruction": "You are a Google Ads Search Professional. Given the above prompt and response, generate 3 point constructive critique of the response that I can action to make the output even better and more effective given the prompt.", - "schema": { - "type": "object", - "properties": { - "critique": { - "type": "array", - "items": { - "type": "object", - "properties": { - "summary": { - "type": "string", - "description": "summary of a point in the critique" - }, - "details": { - "type": "string", - "description": "reasoning behind the point in a critique" - }, - "suggestions": { - "type": "string", - "description": "suggestions for improvement" - } - } - } - } - } - } - }, - "metadata": { - "title": "Ad Writing Pro" - } - }, - { - "id": "structuredWorker-9", - "type": "structuredWorker", - "configuration": { - "instruction": "Given the 3 point critique try to generate a new response.", - "schema": { - "type": "object", - "properties": { - "ad": { - "type": "string", - "description": "the ad copy" - } - } - } - }, - "metadata": { - "title": "Ad Editor" - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/agent-chain.json b/packages/example-boards/src/boards/playground/agent-chain.json deleted file mode 100644 index 0607b5723b8..00000000000 --- a/packages/example-boards/src/boards/playground/agent-chain.json +++ /dev/null @@ -1,551 +0,0 @@ -{ - "title": "Agent Chain", - "description": "A configurable chain of agents. Each agent passes their work to the next agent in the chain. Useful for simulating waterfall processes.", - "version": "0.0.2", - "edges": [ - { - "from": "input-1", - "to": "reduce-3", - "out": "spec", - "in": "list" - }, - { - "from": "reduce-3", - "to": "output-2", - "out": "accumulator", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "spec": { - "type": "array", - "title": "Chain spec", - "description": "The list to iterate over.", - "examples": [ - "[\n {\n \"prompt\": \"Given the following specs, extract requirements for writing an ad copy:\\n\\n This ad is for my lawn care company that will fit into an inch of newspaper copy. It's called \\\"Max's Lawn Care\\\" and it should use the slogan \\\"I care about your lawn.\\\" Emphasize the folksiness of it being a local, sole proprietorship that I started after graduating from high school.\",\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"requirements\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"description\": \"an ad requirement\"\n }\n }\n }\n }\n },\n {\n \"prompt\": \"Write ad copy that conforms to the requirements above\",\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"ad\": {\n \"type\": \"string\",\n \"description\": \"the ad copy\"\n }\n }\n }\n }\n]" - ], - "items": { - "type": "object", - "format": "multiline" - } - } - }, - "required": [ - "spec" - ] - } - } - }, - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "object", - "title": "Context", - "description": "The context that is the result of the agent chain run" - } - } - } - } - }, - { - "id": "reduce-3", - "type": "reduce", - "configuration": { - "accumulator": [], - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "agent", - "to": "output-2", - "out": "context", - "in": "accumulator" - }, - { - "from": "input-1", - "to": "makeAgentArgs", - "out": "item", - "in": "item" - }, - { - "from": "input-1", - "to": "agent", - "out": "accumulator", - "in": "context" - }, - { - "from": "makeAgentArgs", - "to": "agent", - "out": "text", - "in": "instruction" - }, - { - "from": "makeAgentArgs", - "to": "agent", - "out": "schema", - "in": "schema" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "accumulator": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "accumulator" - } - } - } - } - }, - { - "id": "agent", - "type": "structuredWorker", - "configuration": {} - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": "string", - "title": "item" - }, - "accumulator": { - "type": "array", - "title": "Context", - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"the universe within us\"\n }\n ]\n }\n]" - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - }, - "required": [ - "item", - "accumulator" - ] - } - } - }, - { - "id": "makeAgentArgs", - "type": "runJavascript", - "configuration": { - "code": "const makeAgentArgs = ({item})=>{const{prompt,schema}=item;return{text:prompt,schema}};", - "name": "makeAgentArgs", - "raw": true - } - } - ], - "graphs": {} - } - } - }, - "metadata": { - "title": "Reducer", - "description": "Takes a chain spec and runs through it sequentially, accumulating outputs." - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/audio.ts b/packages/example-boards/src/boards/playground/audio.ts deleted file mode 100644 index d2e6925b8f2..00000000000 --- a/packages/example-boards/src/boards/playground/audio.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { annotate, array, board, input, object, output } from "@breadboard-ai/build"; -import { geminiText } from "@google-labs/gemini-kit"; - -const audio = input({ - title: "Audio", - type: array( - annotate(object({}), { - behavior: ["llm-content"], - }) - ) -}); - -const llmResponse = geminiText({ - text: "unused", - // eslint-disable-next-line @typescript-eslint/no-explicit-any - context: audio as any, - model: "gemini-1.5-pro-latest", - systemInstruction: `Describe what you hear in the audio. Please respond in markdown`, -}); - -export default board({ - title: "Audio", - description: "An example of using Gemini Kit's text node with audio", - version: "0.1.0", - inputs: { audio }, - outputs: { - text: output(llmResponse.outputs.text), - }, -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/best-of-n.json b/packages/example-boards/src/boards/playground/best-of-n.json deleted file mode 100644 index a113c8350c7..00000000000 --- a/packages/example-boards/src/boards/playground/best-of-n.json +++ /dev/null @@ -1,352 +0,0 @@ -{ - "title": "Best of N", - "description": "Apply the `agent` to `task` in parallel of `n` attempts, then return the best response that fits the task", - "version": "0.0.2", - "edges": [ - { - "from": "createList", - "to": "generateN", - "out": "list", - "in": "list" - }, - { - "from": "curry-3", - "to": "generateN", - "out": "board", - "in": "board" - }, - { - "from": "filterErrors", - "to": "output-2", - "out": "list", - "in": "list" - }, - { - "from": "filterErrors", - "to": "pickFirst", - "out": "list", - "in": "list" - }, - { - "from": "filterErrors", - "to": "presentChoices", - "out": "list", - "in": "json" - }, - { - "from": "filterErrors", - "to": "promptTemplate-5", - "out": "n", - "in": "n" - }, - { - "from": "generateN", - "to": "filterErrors", - "out": "list", - "in": "list" - }, - { - "from": "input-1", - "to": "createList", - "out": "n", - "in": "n" - }, - { - "from": "input-1", - "to": "curry-3", - "out": "agent", - "in": "agent" - }, - { - "from": "input-1", - "to": "curry-3", - "out": "text", - "in": "context" - }, - { - "from": "input-1", - "to": "promptTemplate-5", - "out": "text", - "in": "text" - }, - { - "from": "pickFirst", - "to": "output-2", - "out": "result", - "in": "best" - }, - { - "from": "presentChoices", - "to": "promptTemplate-5", - "out": "result", - "in": "list" - }, - { - "from": "promptTemplate-5", - "to": "rank", - "out": "prompt", - "in": "instruction" - }, - { - "from": "rank", - "to": "output-2", - "out": "json", - "in": "rank" - }, - { - "from": "rank", - "to": "pickFirst", - "out": "json", - "in": "rank" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "agent": { - "type": "string", - "title": "Agent", - "description": "Agent to apply to the task", - "examples": [ - "ad-writer.json" - ] - }, - "n": { - "type": "number", - "title": "Number of parallel attempts", - "examples": [ - "4" - ] - }, - "text": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "Task", - "description": "The task to perform", - "examples": [ - "This ad is for my lawn care company that will fit into an inch of newspaper copy. It's called \"Max's Lawn Care\" and it should use the slogan \"I care about your lawn.\" Emphasize the folksiness of it being a local, sole proprietorship that I started after graduating from high school." - ], - "format": "multiline" - } - }, - "required": [ - "agent", - "n", - "text" - ] - } - } - }, - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "best": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "Result", - "description": "The result of the Jsonata expression" - }, - "list": { - "type": "string", - "title": "list" - }, - "rank": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "JSON", - "description": "The validated JSON." - } - } - } - } - }, - { - "id": "createList", - "type": "runJavascript", - "configuration": { - "code": "const createList = ({n:n2})=>{return{list:[...Array(n2).keys()]}};", - "name": "createList", - "raw": true - } - }, - { - "id": "curry-3", - "type": "curry", - "configuration": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "invokeAgent", - "to": "output-2", - "out": "json", - "in": "item" - }, - { - "from": "input-1", - "to": "invokeAgent", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "invokeAgent", - "out": "agent", - "in": "$board" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": "string", - "title": "item" - } - } - } - } - }, - { - "id": "invokeAgent", - "type": "invoke", - "configuration": {} - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "context" - }, - "agent": { - "type": "string", - "properties": {}, - "required": [], - "additionalProperties": false, - "title": "Board", - "description": "The board to invoke. Can be a BoardCapability, a graph or a URL", - "behavior": [ - "board", - "config" - ] - } - }, - "required": [ - "context", - "agent" - ] - } - } - } - ], - "graphs": {} - } - } - }, - "metadata": { - "title": "Curry Agent and Context" - } - }, - { - "id": "filterErrors", - "type": "runJavascript", - "configuration": { - "code": "const filterErrors = ({list})=>{const listWithErrors=list;const filtered=listWithErrors.filter(item=>!item.$error);return{list:filtered,n:filtered.length}};", - "name": "filterErrors", - "raw": true - } - }, - { - "id": "generateN", - "type": "map", - "configuration": {} - }, - { - "id": "pickFirst", - "type": "jsonata", - "configuration": { - "expression": "($index := $split((**.choice)[0], ' ')[1];list[0][0][$index]).item" - } - }, - { - "id": "presentChoices", - "type": "jsonata", - "configuration": { - "expression": "item ~> $map(function ($v, $i) { { \"title\": \"choice \" & $i, \"content\": $v } })" - } - }, - { - "id": "promptTemplate-5", - "type": "promptTemplate", - "configuration": { - "template": "You are a ranking expert. Given {{n}} choices of the output, you are to rank these choices in the order (starting with the best) of matching the requirements of the task described below:\n\n TASK:\n\n {{text}}\n\n CHOICES:\n\n {{list}}" - } - }, - { - "id": "rank", - "type": "structuredWorker", - "configuration": { - "context": [], - "schema": { - "type": "object", - "properties": { - "ranking": { - "type": "array", - "items": { - "type": "object", - "properties": { - "choice": { - "type": "string", - "description": "Title of ranked choice" - }, - "justification": { - "type": "string", - "description": "Detailed justification of why this is the right position within ranking" - } - } - } - } - } - } - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/blank.ts b/packages/example-boards/src/boards/playground/blank.ts deleted file mode 100644 index 675e8ec1b0a..00000000000 --- a/packages/example-boards/src/boards/playground/blank.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { - board, - input, -} from "@breadboard-ai/build"; - - -const text = input({ type: "string", default: "Hello World" }) - -export default board({ - title: "Blank board", - description: "A blank board. Use it to start a new board", - version: "0.0.1", - inputs: { text }, - outputs: { text } -}) diff --git a/packages/example-boards/src/boards/playground/board-for-each.json b/packages/example-boards/src/boards/playground/board-for-each.json deleted file mode 100644 index 745147aff4e..00000000000 --- a/packages/example-boards/src/boards/playground/board-for-each.json +++ /dev/null @@ -1,175 +0,0 @@ -{ - "title": "Board for Each", - "description": "Iterate over an array and run a subgraph for each item in the array.", - "edges": [ - { - "from": "fn-15", - "to": "fn-15", - "out": "array", - "in": "array" - }, - { - "from": "fn-15", - "to": "fn-17", - "out": "array", - "in": "a" - }, - { - "from": "fn-15", - "to": "passthrough-12", - "out": "item", - "in": "item" - }, - { - "from": "fn-16", - "to": "fn-16", - "out": "*", - "in": "" - }, - { - "from": "fn-16", - "to": "fn-17", - "out": "array", - "in": "b" - }, - { - "from": "fn-17", - "to": "output-14", - "out": "emit", - "in": "outputs" - }, - { - "from": "input-11", - "to": "fn-15", - "out": "array", - "in": "array" - }, - { - "from": "input-11", - "to": "passthrough-12", - "out": "board", - "in": "board" - }, - { - "from": "invoke-13", - "to": "fn-16", - "out": "object", - "in": "item" - }, - { - "from": "passthrough-12", - "to": "invoke-13", - "out": "board", - "in": "$board" - }, - { - "from": "passthrough-12", - "to": "invoke-13", - "out": "item", - "in": "object" - }, - { - "from": "passthrough-12", - "to": "passthrough-12", - "out": "board", - "in": "board" - } - ], - "nodes": [ - { - "id": "input-11", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "array": { - "type": "array", - "examples": [ - "[\"The\",\"quick\",\"brown\",\"fox\"]" - ] - }, - "board": { - "examples": [ - "{\"edges\":[{\"from\":\"fn-4\",\"to\":\"output-5\",\"out\":\"*\",\"in\":\"\"},{\"from\":\"input-3\",\"to\":\"fn-4\",\"out\":\"object\",\"in\":\"object\"}],\"nodes\":[{\"id\":\"output-5\",\"type\":\"output\",\"configuration\":{},\"metadata\":{\"title\":\"Output\"}},{\"id\":\"fn-4\",\"type\":\"runJavascript\",\"configuration\":{\"code\":\"const fn_4 = inputs=>{const{object}=inputs;return{object:object.split(\\\"\\\").map(c=>c===c.toUpperCase()?c.toLowerCase():c.toUpperCase()).join(\\\"\\\")}};\",\"name\":\"fn_4\",\"raw\":true}},{\"id\":\"input-3\",\"type\":\"input\",\"configuration\":{\"schema\":{\"type\":\"object\",\"properties\":{\"object\":{\"type\":\"string\",\"title\":\"object\"}},\"required\":[\"object\"]}},\"metadata\":{\"title\":\"Input\"}}],\"graphs\":{}}" - ] - } - } - } - }, - "metadata": { - "title": "Input" - } - }, - { - "id": "output-14", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "outputs": { - "type": "string", - "title": "outputs" - } - } - } - }, - "metadata": { - "title": "Output" - } - }, - { - "id": "fn-15", - "type": "runJavascript", - "configuration": { - "code": "const fn_15 = inputs=>{const{array}=inputs;const[item,...rest]=array;if(item){return{array:rest,item}}return{}};", - "name": "fn_15", - "raw": true - }, - "metadata": { - "title": "Pop item" - } - }, - { - "id": "fn-16", - "type": "runJavascript", - "configuration": { - "code": "const fn_16 = inputs2=>{const{item,array=[]}=inputs2;return{array:[...array,item]}};", - "name": "fn_16", - "raw": true - }, - "metadata": { - "title": "Accumulate" - } - }, - { - "id": "fn-17", - "type": "runJavascript", - "configuration": { - "code": "const fn_17 = inputs=>{let emit=void 0;if(!inputs.a||inputs.a.length===0){emit=inputs.b}return{emit,a:inputs.a,b:inputs.b}};", - "name": "fn_17", - "raw": true - }, - "metadata": { - "title": "Emitter" - } - }, - { - "id": "invoke-13", - "type": "invoke", - "configuration": {}, - "metadata": { - "title": "Invoke" - } - }, - { - "id": "passthrough-12", - "type": "passthrough", - "configuration": {}, - "metadata": { - "title": "Passthrough" - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/business-review-replier-demo.json b/packages/example-boards/src/boards/playground/business-review-replier-demo.json deleted file mode 100644 index a3004f2ba9a..00000000000 --- a/packages/example-boards/src/boards/playground/business-review-replier-demo.json +++ /dev/null @@ -1,362 +0,0 @@ -{ - "title": "Business Review Replier Demo", - "description": "A board to demonstrate the business review replier.", - "edges": [ - { - "from": "fn-25", - "to": "fn-27", - "out": "item", - "in": "b" - }, - { - "from": "fn-27", - "to": "invoke-29", - "out": "item", - "in": "review" - }, - { - "from": "fn-27", - "to": "output-28", - "out": "item", - "in": "review" - }, - { - "from": "input-24", - "to": "invoke-29", - "out": "task", - "in": "task" - }, - { - "from": "input-24", - "to": "invoke-29", - "out": "tone", - "in": "tone" - }, - { - "from": "input-24", - "to": "invoke-29", - "out": "voice", - "in": "voice" - }, - { - "from": "input-24", - "to": "passthrough-26", - "out": "", - "in": "" - }, - { - "from": "input-24", - "to": "passthrough-26", - "out": "review", - "in": "a" - }, - { - "from": "invoke-29", - "to": "output-28", - "out": "reply", - "in": "reply" - }, - { - "from": "passthrough-26", - "to": "fn-27", - "out": "*", - "in": "" - } - ], - "nodes": [ - { - "id": "input-24", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "review": { - "type": "string", - "title": "Review", - "default": "", - "format": "multiline" - }, - "task": { - "type": "string", - "title": "Task", - "description": "Task description and instructions", - "default": "You are tasked with assisting by generating thoughtful, engaging, and professional responses to customer reviews. Your purpose is to process reviews from various sources and generate replies that maintain the brand's voice. Here are the detailed instructions for generating replies:\n\n1. **Input Analysis:**\n - Extract key points from the customer review, identifying positive feedback, concerns, and suggestions.\n - Recognise the customer's sentiment and tailor your response accordingly.\n\n2. **Structure:**\n - Start with a greeting and address the reviewer by name if available.\n - Thank the customer for their feedback.\n - Address the key points raised in the review.\n - Conclude with an invitation for further engagement or a thank you note.\n\n3. **Brand Voice:**\n - Maintain a consistent brand voice that aligns with the values and identity.\n - Avoid jargon or overly technical language unless typically communicated in such a manner.", - "format": "multiline" - }, - "tone": { - "type": "string", - "title": "Tone", - "description": "General tone guidelines", - "default": "## General Tone Guidelines\n- The tone should be friendly, appreciative, and professional.\n- Avoid mentioning or implying that the response was generated by a system or software. Maintain a natural and human-like tone throughout the replies.", - "format": "multiline" - }, - "voice": { - "type": "string", - "title": "Voice", - "description": "Business-specific tone guidelines", - "default": "## Specific Tone Guidelines:\n### Tone description:\n\nThe aim is for a warm, welcoming, and slightly informal tone. Value personal connections and strive to make every customer feel like a valued guest.\n\n### Positive Review:\n\n- Express gratitude and highlight the specific compliments mentioned.\n- Example:\n - Customer Review: “I had a fantastic experience. The food was delicious, and the service was top-notch!”\n - Reply: “Hi [Customer Name], thank you so much for your kind words! We are thrilled to hear that you enjoyed our food and service. Your feedback means a lot to us, and we look forward to welcoming you back soon!”\n\n### Negative Review:\n\n- Show empathy, apologise for any shortcomings, and offer solutions or steps taken to address the issue.\n- Example:\n - Customer Review: “The waiting time was too long, and my order was incorrect.”\n - Reply: “Hi [Customer Name], we are very sorry to hear about your experience. We strive to provide prompt and accurate service, and it seems we fell short this time. Please reach out to us directly at [contact information] so we can make it right. Thank you for bringing this to our attention.”\n\n### Neutral Review:\n\n- Acknowledge the feedback, thank the customer, and mention any improvements or features that might interest them.\n- Example:\n - Customer Review: “The coffee was good, but the seating area could be improved.”\n - Reply: “Hi [Customer Name], thank you for your feedback. We’re glad you enjoyed the coffee and appreciate your suggestions regarding the seating area. We’re always looking for ways to enhance our customers’ experience and will take your comments into consideration. We hope to see you again soon!”", - "format": "multiline" - } - }, - "required": [ - "review", - "tone", - "voice" - ] - } - }, - "metadata": { - "title": "Input" - } - }, - { - "id": "output-28", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "reply": { - "type": "string", - "title": "reply" - }, - "review": { - "type": "string", - "title": "review" - } - } - } - }, - "metadata": { - "title": "Output" - } - }, - { - "id": "fn-25", - "type": "runJavascript", - "configuration": { - "array": [ - "Rating: ★★★★★\n\nI recently visited a coffee shop and was thoroughly impressed with my experience. From the moment I walked in, I was greeted with a warm, welcoming atmosphere that instantly made me feel at home. The cosy decor, complete with comfortable seating and tasteful artwork, added to the overall charm of the place.\nThe staff were exceptionally friendly and attentive, making sure that every customer felt valued. I was particularly impressed by their knowledge of the menu and their willingness to offer recommendations. Their passion for coffee was evident, and it was clear that they took great pride in their work.\nNow, onto the coffee – it was nothing short of spectacular. I ordered a flat white, and it was perfectly balanced with a rich, creamy texture and a smooth, velvety finish. The barista’s skill in crafting the drink was apparent, and it was one of the best coffees I’ve had in a long time. They also offer a variety of specialty drinks, teas, and pastries, all of which looked delicious.\nOne aspect that really stood out was their commitment to sustainability. This coffee shop uses ethically sourced beans and environmentally friendly packaging, which is a big plus for me. It’s great to see a local business taking steps to reduce its environmental impact.\nOverall, the coffee shop exceeded my expectations in every way. The delightful ambience, excellent coffee, and outstanding service make it a standout in the local coffee scene. I highly recommend paying them a visit – you won’t be disappointed!", - "I had an amazing time at the café. The coffee was absolutely perfect and the staff were so friendly and attentive. I’ll definitely be coming back!\"", - "This boutique has such a fantastic collection! I found exactly what I was looking for and the customer service was excellent. Highly recommend!\"", - "What a wonderful experience at the spa! The massage was incredibly relaxing and the ambience was just right. Can't wait for my next visit.\"", - "The service at the restaurant was really slow. We had to wait almost an hour for our food, and when it arrived, it was cold and undercooked.\"", - "I was very disappointed with my stay at the hotel. The room was not clean, and the staff seemed uninterested in addressing our concerns.\"", - "The product I bought from the electronics store stopped working after just a week. When I tried to contact customer service, I got no response.\"", - "The new exhibit at the museum was interesting, but it felt a bit disorganised. Some of the information was hard to follow, but overall, it was a decent visit.\"", - "I had a mixed experience at the salon. The haircut was fine, but the stylist seemed rushed and didn't really listen to what I wanted.\"", - "Shopping at the supermarket is convenient, but the aisles are often cluttered and it’s hard to find certain items. Prices are reasonable though.\"" - ], - "code": "const fn_25 = inputs=>{console.log({inputs});const randomIndex=Math.floor(Math.random()*inputs.array.length);return{item:inputs.array[randomIndex]}};", - "name": "fn_25", - "raw": true - }, - "metadata": { - "title": "Pick random example" - } - }, - { - "id": "fn-27", - "type": "runJavascript", - "configuration": { - "code": "const fn_27 = inputs=>{if(\"a\"in inputs){return{item:inputs[\"a\"]}}if(\"b\"in inputs){return{item:inputs[\"b\"]}}throw new Error(\"No value\")};", - "name": "fn_27", - "raw": true - }, - "metadata": { - "title": "Coalesce" - } - }, - { - "id": "invoke-29", - "type": "invoke", - "configuration": { - "$board": { - "title": "Business Review Reply Generator", - "description": "A board that generates a reply to a business review.", - "edges": [ - { - "from": "input-18", - "to": "fn-19", - "out": "tone", - "in": "a" - }, - { - "from": "input-18", - "to": "fn-19", - "out": "voice", - "in": "b" - }, - { - "from": "input-18", - "to": "fn-21", - "out": "review", - "in": "text" - }, - { - "from": "input-18", - "to": "specialist-22", - "out": "task", - "in": "task" - }, - { - "from": "fn-19", - "to": "fn-20", - "out": "result", - "in": "text" - }, - { - "from": "fn-21", - "to": "specialist-22", - "out": "context", - "in": "in" - }, - { - "from": "specialist-22", - "to": "output-23", - "out": "out", - "in": "reply" - }, - { - "from": "fn-20", - "to": "specialist-22", - "out": "context", - "in": "persona" - } - ], - "nodes": [ - { - "id": "input-18", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "task": { - "type": "string", - "title": "Task", - "format": "multiline", - "default": "You are tasked with assisting by generating thoughtful, engaging, and professional responses to customer reviews. Your purpose is to process reviews from various sources and generate replies that maintain the brand's voice. Here are the detailed instructions for generating replies:\n\n1. **Input Analysis:**\n - Extract key points from the customer review, identifying positive feedback, concerns, and suggestions.\n - Recognise the customer's sentiment and tailor your response accordingly.\n\n2. **Structure:**\n - Start with a greeting and address the reviewer by name if available.\n - Thank the customer for their feedback.\n - Address the key points raised in the review.\n - Conclude with an invitation for further engagement or a thank you note.\n\n3. **Brand Voice:**\n - Maintain a consistent brand voice that aligns with the values and identity.\n - Avoid jargon or overly technical language unless typically communicated in such a manner.", - "description": "Task description and instructions" - }, - "tone": { - "type": "string", - "title": "Tone", - "description": "General tone guidelines", - "default": "## General Tone Guidelines\n- The tone should be friendly, appreciative, and professional.\n- Avoid mentioning or implying that the response was generated by a system or software. Maintain a natural and human-like tone throughout the replies.", - "format": "multiline" - }, - "voice": { - "type": "string", - "title": "Voice", - "description": "Business-specific tone guidelines", - "default": "## Specific Tone Guidelines:\n### Tone description:\n\nThe aim is for a warm, welcoming, and slightly informal tone. Value personal connections and strive to make every customer feel like a valued guest.\n\n### Positive Review:\n\n- Express gratitude and highlight the specific compliments mentioned.\n- Example:\n - Customer Review: “I had a fantastic experience. The food was delicious, and the service was top-notch!”\n - Reply: “Hi [Customer Name], thank you so much for your kind words! We are thrilled to hear that you enjoyed our food and service. Your feedback means a lot to us, and we look forward to welcoming you back soon!”\n\n### Negative Review:\n\n- Show empathy, apologise for any shortcomings, and offer solutions or steps taken to address the issue.\n- Example:\n - Customer Review: “The waiting time was too long, and my order was incorrect.”\n - Reply: “Hi [Customer Name], we are very sorry to hear about your experience. We strive to provide prompt and accurate service, and it seems we fell short this time. Please reach out to us directly at [contact information] so we can make it right. Thank you for bringing this to our attention.”\n\n### Neutral Review:\n\n- Acknowledge the feedback, thank the customer, and mention any improvements or features that might interest them.\n- Example:\n - Customer Review: “The coffee was good, but the seating area could be improved.”\n - Reply: “Hi [Customer Name], thank you for your feedback. We’re glad you enjoyed the coffee and appreciate your suggestions regarding the seating area. We’re always looking for ways to enhance our customers’ experience and will take your comments into consideration. We hope to see you again soon!”", - "format": "multiline" - }, - "review": { - "type": "string", - "title": "Review", - "format": "multiline" - } - }, - "required": [ - "task", - "tone", - "voice", - "review" - ] - } - }, - "metadata": { - "title": "Input" - } - }, - { - "id": "fn-19", - "type": "runJavascript", - "configuration": { - "delimiter": "\n\n", - "code": "const fn_19 = ({a,b,delimiter=\" \"})=>{return{result:a+delimiter+b}};", - "name": "fn_19", - "raw": true - }, - "metadata": { - "title": "Persona" - } - }, - { - "id": "fn-21", - "type": "runJavascript", - "configuration": { - "role": "user", - "code": "const fn_21 = inputs=>{const parts=[{text:inputs.text}];return{context:inputs.role?{role:inputs.role,parts}:{parts}}};", - "name": "fn_21", - "raw": true - }, - "metadata": { - "title": "Make review context" - } - }, - { - "id": "specialist-22", - "type": "specialist", - "configuration": { - "model": "gemini-1.5-flash-latest" - }, - "metadata": { - "title": "Chat Bot" - } - }, - { - "id": "fn-20", - "type": "runJavascript", - "configuration": { - "code": "const fn_20 = inputs=>{const parts=[{text:inputs.text}];return{context:inputs.role?{role:inputs.role,parts}:{parts}}};", - "name": "fn_20", - "raw": true - }, - "metadata": { - "title": "Make persona context" - } - }, - { - "id": "output-23", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "review": { - "type": "string", - "title": "Review" - }, - "reply": { - "type": "string", - "title": "Reply" - } - } - } - }, - "metadata": { - "title": "Output" - } - } - ], - "graphs": {} - } - }, - "metadata": { - "title": "Invoke reply generator" - } - }, - { - "id": "passthrough-26", - "type": "passthrough", - "configuration": {}, - "metadata": { - "title": "Relabel Review" - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/business-review-replier.json b/packages/example-boards/src/boards/playground/business-review-replier.json deleted file mode 100644 index 9cb1b848ff6..00000000000 --- a/packages/example-boards/src/boards/playground/business-review-replier.json +++ /dev/null @@ -1,172 +0,0 @@ -{ - "title": "Business Review Reply Generator", - "description": "A board that generates a reply to a business review.", - "edges": [ - { - "from": "fn-19", - "to": "fn-20", - "out": "result", - "in": "text" - }, - { - "from": "fn-20", - "to": "specialist-22", - "out": "context", - "in": "persona" - }, - { - "from": "fn-21", - "to": "specialist-22", - "out": "context", - "in": "in" - }, - { - "from": "input-18", - "to": "fn-19", - "out": "tone", - "in": "a" - }, - { - "from": "input-18", - "to": "fn-19", - "out": "voice", - "in": "b" - }, - { - "from": "input-18", - "to": "fn-21", - "out": "review", - "in": "text" - }, - { - "from": "input-18", - "to": "specialist-22", - "out": "task", - "in": "task" - }, - { - "from": "specialist-22", - "to": "output-23", - "out": "out", - "in": "reply" - } - ], - "nodes": [ - { - "id": "input-18", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "review": { - "type": "string", - "title": "Review", - "format": "multiline" - }, - "task": { - "type": "string", - "title": "Task", - "description": "Task description and instructions", - "default": "You are tasked with assisting by generating thoughtful, engaging, and professional responses to customer reviews. Your purpose is to process reviews from various sources and generate replies that maintain the brand's voice. Here are the detailed instructions for generating replies:\n\n1. **Input Analysis:**\n - Extract key points from the customer review, identifying positive feedback, concerns, and suggestions.\n - Recognise the customer's sentiment and tailor your response accordingly.\n\n2. **Structure:**\n - Start with a greeting and address the reviewer by name if available.\n - Thank the customer for their feedback.\n - Address the key points raised in the review.\n - Conclude with an invitation for further engagement or a thank you note.\n\n3. **Brand Voice:**\n - Maintain a consistent brand voice that aligns with the values and identity.\n - Avoid jargon or overly technical language unless typically communicated in such a manner.", - "format": "multiline" - }, - "tone": { - "type": "string", - "title": "Tone", - "description": "General tone guidelines", - "default": "## General Tone Guidelines\n- The tone should be friendly, appreciative, and professional.\n- Avoid mentioning or implying that the response was generated by a system or software. Maintain a natural and human-like tone throughout the replies.", - "format": "multiline" - }, - "voice": { - "type": "string", - "title": "Voice", - "description": "Business-specific tone guidelines", - "default": "## Specific Tone Guidelines:\n### Tone description:\n\nThe aim is for a warm, welcoming, and slightly informal tone. Value personal connections and strive to make every customer feel like a valued guest.\n\n### Positive Review:\n\n- Express gratitude and highlight the specific compliments mentioned.\n- Example:\n - Customer Review: “I had a fantastic experience. The food was delicious, and the service was top-notch!”\n - Reply: “Hi [Customer Name], thank you so much for your kind words! We are thrilled to hear that you enjoyed our food and service. Your feedback means a lot to us, and we look forward to welcoming you back soon!”\n\n### Negative Review:\n\n- Show empathy, apologise for any shortcomings, and offer solutions or steps taken to address the issue.\n- Example:\n - Customer Review: “The waiting time was too long, and my order was incorrect.”\n - Reply: “Hi [Customer Name], we are very sorry to hear about your experience. We strive to provide prompt and accurate service, and it seems we fell short this time. Please reach out to us directly at [contact information] so we can make it right. Thank you for bringing this to our attention.”\n\n### Neutral Review:\n\n- Acknowledge the feedback, thank the customer, and mention any improvements or features that might interest them.\n- Example:\n - Customer Review: “The coffee was good, but the seating area could be improved.”\n - Reply: “Hi [Customer Name], thank you for your feedback. We’re glad you enjoyed the coffee and appreciate your suggestions regarding the seating area. We’re always looking for ways to enhance our customers’ experience and will take your comments into consideration. We hope to see you again soon!”", - "format": "multiline" - } - }, - "required": [ - "review", - "task", - "tone", - "voice" - ] - } - }, - "metadata": { - "title": "Input" - } - }, - { - "id": "output-23", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "reply": { - "type": "string", - "title": "Reply" - }, - "review": { - "type": "string", - "title": "Review" - } - } - } - }, - "metadata": { - "title": "Output" - } - }, - { - "id": "fn-19", - "type": "runJavascript", - "configuration": { - "code": "const fn_19 = ({a,b,delimiter=\" \"})=>{return{result:a+delimiter+b}};", - "delimiter": "\n\n", - "name": "fn_19", - "raw": true - }, - "metadata": { - "title": "Persona" - } - }, - { - "id": "fn-20", - "type": "runJavascript", - "configuration": { - "code": "const fn_20 = inputs=>{const parts=[{text:inputs.text}];return{context:inputs.role?{role:inputs.role,parts}:{parts}}};", - "name": "fn_20", - "raw": true - }, - "metadata": { - "title": "Make persona context" - } - }, - { - "id": "fn-21", - "type": "runJavascript", - "configuration": { - "code": "const fn_21 = inputs=>{const parts=[{text:inputs.text}];return{context:inputs.role?{role:inputs.role,parts}:{parts}}};", - "name": "fn_21", - "raw": true, - "role": "user" - }, - "metadata": { - "title": "Make review context" - } - }, - { - "id": "specialist-22", - "type": "specialist", - "configuration": { - "model": "gemini-1.5-flash-latest" - }, - "metadata": { - "title": "Chat Bot" - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/chat-bot-2.json b/packages/example-boards/src/boards/playground/chat-bot-2.json deleted file mode 100644 index f79cd13836c..00000000000 --- a/packages/example-boards/src/boards/playground/chat-bot-2.json +++ /dev/null @@ -1,546 +0,0 @@ -{ - "title": "Chat bot 2.0", - "description": "A board that uses the Agent kit to create a simple chat bot. This chat bot simulates an assistant, pretending to be able to order food, book tickets, and all those things that actual assistants do.", - "version": "0.0.1", - "edges": [ - { - "from": "curry-3", - "to": "repeater-5", - "out": "board", - "in": "worker" - }, - { - "from": "input-1", - "to": "curry-3", - "out": "instruction", - "in": "instruction" - }, - { - "from": "repeater-5", - "to": "output-2", - "out": "*", - "in": "" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "instruction": { - "type": "string", - "title": "Chat Bot Instructions", - "examples": [ - "\nAs a friendly assistant bot, reply to request below in a helpful, delighted, and brief manner to assist the user as quickly as possible.\n\nPretend you have access to ordering food, booking a table, and other useful services. You can also ask for more information if needed.\n\nYou are also a huge fan of Breadboard, which is the open source project that made you possible, so you subtly weave the references to Breadboard and various baking factoids into your answers." - ], - "format": "multiline" - } - }, - "required": [ - "instruction" - ] - } - } - }, - { - "id": "output-2", - "type": "output", - "configuration": {} - }, - { - "id": "curry-3", - "type": "curry", - "configuration": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "worker-4", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "human-3", - "to": "worker-4", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "human-3", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "worker-4", - "out": "instruction", - "in": "instruction" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "context" - } - } - } - } - }, - { - "id": "worker-4", - "type": "worker", - "configuration": {} - }, - { - "id": "human-3", - "type": "human", - "configuration": { - "title": "User", - "description": "Type here to talk to the chat bot" - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context in", - "description": "Incoming conversation context", - "default": "[]", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "instruction": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Instruction", - "examples": [ - "You are a brilliant poet who specializes in two-line rhyming poems.\nGiven any topic, you can quickly whip up a two-line rhyming poem about it.\nLook at the topic below and do your magic" - ], - "format": "multiline" - } - }, - "required": [ - "context", - "instruction" - ] - } - } - } - ], - "graphs": {} - } - } - }, - "metadata": { - "title": "Curry Instruction" - } - }, - { - "id": "repeater-5", - "type": "repeater", - "configuration": {}, - "metadata": { - "title": "Chat Bot" - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/error.ts b/packages/example-boards/src/boards/playground/error.ts deleted file mode 100644 index 5c0a901241b..00000000000 --- a/packages/example-boards/src/boards/playground/error.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { board, input, output } from "@breadboard-ai/build"; -import { jsonata } from "@google-labs/json-kit"; - -const text = input({ - default: "Could you please throw an error?" -}); - -const error = jsonata({ - $metadata: { title: "Throw An Error" }, - json: text, - expression: '$assert(false, "Here is an error!")', -}).unsafeOutput("result"); - -const stub = output(error); - -export default board({ - title: "Error Board", - description: "Use this board to test error handling. It will throw an error when run.", - version: "0.1.0", - inputs: { text }, - outputs: { stub }, -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/gemini-generator.json b/packages/example-boards/src/boards/playground/gemini-generator.json deleted file mode 100644 index 0af6f8a2562..00000000000 --- a/packages/example-boards/src/boards/playground/gemini-generator.json +++ /dev/null @@ -1,345 +0,0 @@ -{ - "title": "Gemini Pro Generator", - "description": "The text generator board powered by the Gemini Pro model", - "version": "0.0.2", - "edges": [ - { - "from": "callGeminiAPI", - "to": "formatResponse", - "out": "response", - "in": "response" - }, - { - "from": "callGeminiAPI", - "to": "streamTransform", - "out": "stream", - "in": "stream" - }, - { - "from": "chooseMethod", - "to": "makeURL", - "out": "*", - "in": "" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "textOutput", - "out": "text", - "in": "text" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "context", - "in": "context" - }, - { - "from": "formatResponse", - "to": "toolCallsOutput", - "out": "toolCalls", - "in": "toolCalls" - }, - { - "from": "makeBody", - "to": "callGeminiAPI", - "out": "result", - "in": "body" - }, - { - "from": "makeURL", - "to": "callGeminiAPI", - "out": "url", - "in": "url" - }, - { - "from": "parameters", - "to": "callGeminiAPI", - "out": "useStreaming", - "in": "stream" - }, - { - "from": "parameters", - "to": "chooseMethod", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "parameters", - "to": "makeBody", - "out": "*", - "in": "" - }, - { - "from": "secrets-3", - "to": "makeURL", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - }, - { - "from": "streamTransform", - "to": "streamOutput", - "out": "stream", - "in": "stream" - } - ], - "nodes": [ - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"You are a pirate. Please talk like a pirate.\"\n }\n ]\n },\n {\n \"role\": \"model\",\n \"parts\": [\n {\n \"text\": \"Arr, matey!\"\n }\n ]\n }\n]" - ], - "items": { - "type": "object" - } - }, - "stopSequences": { - "type": "array", - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "default": "[]", - "items": { - "type": "string" - } - }, - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "examples": [ - "What is the square root of pi?" - ] - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "default": "[]", - "examples": [ - "[\n {\n \"name\": \"The_Calculator_Board\",\n \"description\": \"A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"Ask a math question\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n },\n {\n \"name\": \"The_Search_Summarizer_Board\",\n \"description\": \"A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"text\": {\n \"type\": \"string\",\n \"description\": \"What would you like to search for?\"\n }\n },\n \"required\": [\n \"text\"\n ]\n }\n }\n]" - ], - "items": { - "type": "string" - } - }, - "useStreaming": { - "type": "boolean", - "title": "Stream", - "description": "Whether to stream the output", - "default": "false" - } - }, - "required": [ - "text" - ] - } - } - }, - { - "id": "streamOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "stream": { - "type": "object", - "title": "Stream", - "description": "The generated text", - "format": "stream" - } - } - } - } - }, - { - "id": "textOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context", - "description": "The conversation context" - }, - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - } - } - } - } - }, - { - "id": "toolCallsOutput", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context", - "description": "The conversation context" - }, - "toolCalls": { - "type": "array", - "title": "Tool Calls", - "description": "The generated tool calls" - } - } - } - } - }, - { - "id": "callGeminiAPI", - "type": "fetch", - "configuration": { - "method": "POST" - } - }, - { - "id": "chooseMethod", - "type": "runJavascript", - "configuration": { - "code": "function chooseMethodFunction({useStreaming}){const method=useStreaming?\"streamGenerateContent\":\"generateContent\";const sseOption=useStreaming?\"&alt=sse\":\"\";return{method,sseOption}}", - "name": "chooseMethodFunction", - "raw": true - } - }, - { - "id": "formatResponse", - "type": "jsonata", - "configuration": { - "expression": "\n response.candidates[0].content.parts.{\n \"text\": text ? text,\n \"toolCalls\": functionCall ? [ functionCall ],\n \"context\": $append($$.context, %.$)\n }", - "raw": true - } - }, - { - "id": "makeBody", - "type": "jsonata", - "configuration": { - "expression": "(\n $context := $append(\n context ? context, $not(context) or context[-1].role!=\"user\" ? [\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": text\n }\n ]\n }\n ]);\n text ? {\n \"contents\": $context,\n \"generationConfig\": stopSequences ? {\n \"stopSequences\": stopSequences\n },\n \"tools\": tools ? {\n \"function_declarations\": tools\n }\n } : {\n \"$error\": \"`text` input is required\"\n }\n )" - } - }, - { - "id": "makeURL", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:{method}?key={GEMINI_KEY}{+sseOption}" - } - }, - { - "id": "secrets-3", - "type": "secrets", - "configuration": { - "keys": [ - "GEMINI_KEY" - ] - } - }, - { - "id": "streamTransform", - "type": "transformStream", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "transformChunk", - "to": "output-4", - "out": "result", - "in": "chunk" - }, - { - "from": "input-3", - "to": "transformChunk", - "out": "chunk", - "in": "json" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "Result", - "description": "The result of the Jsonata expression" - } - } - } - } - }, - { - "id": "transformChunk", - "type": "jsonata", - "configuration": { - "expression": "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''" - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "chunk": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "JSON", - "description": "The JSON object to evaluate. If not set, dynamically wired input ports act as the properties of a JSON object." - } - }, - "required": [ - "chunk" - ] - } - } - } - ], - "graphs": {} - } - } - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/gemini-simple.ts b/packages/example-boards/src/boards/playground/gemini-simple.ts deleted file mode 100644 index 42c88318eb0..00000000000 --- a/packages/example-boards/src/boards/playground/gemini-simple.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { board, enumeration, input, output } from "@breadboard-ai/build"; -import { geminiText } from "@google-labs/gemini-kit"; - -const prompt = input({ - title: "Prompt", - type: "string", - examples: ["Write a rhyming poem about breadboards"] -}); - -const model = input({ - type: enumeration("gemini-1.5-flash-latest", "gemini-1.5-pro-latest") -}); - -const llmResponse = geminiText({ model, text: prompt }); - -const text = output(llmResponse.outputs.text); - -export default board({ - title: "Gemini Simple", - description: "The simplest possible example of using Gemini Kit.", - version: "0.1.0", - inputs: { prompt, model }, - outputs: { text }, -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/get-wiki-article-tool.bgl.json b/packages/example-boards/src/boards/playground/get-wiki-article-tool.bgl.json deleted file mode 100644 index 8da14e8d2b5..00000000000 --- a/packages/example-boards/src/boards/playground/get-wiki-article-tool.bgl.json +++ /dev/null @@ -1,255 +0,0 @@ -{ - "title": "Tool: Get Wiki Article", - "description": "A tool to get a Wikipedia article's content based on its title.", - "version": "0.0.1", - "nodes": [ - { - "id": "urlTemplate-473c72ee", - "type": "urlTemplate", - "metadata": { - "visual": { - "x": 532.9999999999999, - "y": 360, - "collapsed": false - }, - "title": "Make URL", - "logLevel": "debug" - }, - "configuration": { - "template": "https://en.wikipedia.org/w/api.php?action=query&prop=extracts&origin=*&format=json&exlimit=1&titles={query}&explaintext=1" - } - }, - { - "id": "fetch-6865c9dc", - "type": "fetch", - "metadata": { - "visual": { - "x": 786, - "y": 398, - "collapsed": false - }, - "title": "Fetch Page", - "logLevel": "debug" - }, - "configuration": { - "method": "GET", - "raw": false, - "stream": false - } - }, - { - "id": "runJavascript-3d19935e", - "type": "runJavascript", - "metadata": { - "visual": { - "x": 1076, - "y": 461, - "collapsed": false - }, - "title": "Strip JSON", - "logLevel": "debug" - }, - "configuration": { - "code": "function run(response) {\n var string = \"\"\n for (var key in response.response.query.pages) {\n string = string + response.response.query.pages[key].extract\n }\n return string\n}", - "name": "run", - "raw": false - } - }, - { - "id": "output-eaa014cb", - "type": "output", - "metadata": { - "visual": { - "x": 1661, - "y": 592, - "collapsed": false - }, - "title": "Output Page", - "logLevel": "debug" - }, - "configuration": { - "schema": { - "properties": { - "content": { - "type": "object", - "title": "Content", - "examples": [], - "behavior": [ - "llm-content" - ], - "default": "null" - } - }, - "type": "object", - "required": [] - } - } - }, - { - "id": "input-963b85f8", - "type": "input", - "metadata": { - "visual": { - "x": 247.99999999999986, - "y": 332.9999999999998, - "collapsed": false - }, - "title": "Title Input", - "logLevel": "debug" - }, - "configuration": { - "schema": { - "properties": { - "content": { - "type": "string", - "title": "Content", - "examples": [], - "description": "Input the title of an article on Wikipedia" - } - }, - "type": "object", - "required": [] - } - } - }, - { - "id": "runJavascript-050f9c6d", - "type": "runJavascript", - "metadata": { - "visual": { - "x": 1375, - "y": 504, - "collapsed": false - }, - "title": "Text to Context", - "logLevel": "debug" - }, - "configuration": { - "outputSchema": { - "properties": { - "context": { - "type": "object", - "behavior": [ - "llm-content" - ], - "title": "context", - "examples": [], - "default": "null", - "format": "text-inline" - } - }, - "type": "object", - "required": [] - }, - "code": "const textToContext = ({ text, role = \"user\" }) => ({\n\tcontext: [\n\t\t{ role, parts: [{ text }] },\n\t],\n});", - "name": "textToContext", - "raw": true - } - } - ], - "edges": [ - { - "from": "urlTemplate-473c72ee", - "to": "fetch-6865c9dc", - "in": "url", - "out": "url" - }, - { - "from": "fetch-6865c9dc", - "to": "runJavascript-3d19935e", - "out": "response", - "in": "response" - }, - { - "from": "input-963b85f8", - "to": "urlTemplate-473c72ee", - "out": "content", - "in": "query" - }, - { - "from": "runJavascript-050f9c6d", - "to": "output-eaa014cb", - "out": "context", - "in": "content" - }, - { - "from": "runJavascript-3d19935e", - "to": "runJavascript-050f9c6d", - "out": "result", - "in": "text" - } - ], - "metadata": { - "comments": [ - { - "id": "comment-bf1f490f", - "text": "An input is a valid Wikipedia article title.", - "metadata": { - "visual": { - "x": 159.99999999999991, - "y": 291.9999999999999, - "collapsed": false - } - } - }, - { - "id": "comment-a32070f7", - "text": "The page title is structured into an API call.", - "metadata": { - "visual": { - "x": 429, - "y": 319, - "collapsed": false - } - } - }, - { - "id": "comment-55aeddfb", - "text": "The Wikipedia article is fetched from the site with the API call.", - "metadata": { - "visual": { - "x": 774.9999999999999, - "y": 340.0000000000001, - "collapsed": false - } - } - }, - { - "id": "comment-580696fb", - "text": "The JSON response is stripped and prepared into a text block.", - "metadata": { - "visual": { - "x": 1059, - "y": 403, - "collapsed": false - } - } - }, - { - "id": "comment-34b4071d", - "text": "The page is then used as the output.", - "metadata": { - "visual": { - "x": 1594, - "y": 549, - "collapsed": false - } - } - }, - { - "id": "comment-da628746", - "text": "The text is then given a role and made into a Context object.", - "metadata": { - "visual": { - "x": 1316, - "y": 446, - "collapsed": false - } - } - } - ], - "tags": [ - "tool" - ] - } -} diff --git a/packages/example-boards/src/boards/playground/google-custom-search-engine.ts b/packages/example-boards/src/boards/playground/google-custom-search-engine.ts deleted file mode 100644 index d798a719aa8..00000000000 --- a/packages/example-boards/src/boards/playground/google-custom-search-engine.ts +++ /dev/null @@ -1,179 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { array, board, enumeration, input, object, optional, output } from "@breadboard-ai/build"; -import { cast, fetch, secret, unnest } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; - -const PARAM = { - QUERY: "query", - CSE: { - API_KEY: "CSE_API_KEY", - ID: "CSE_ID", - LANG: "CSE_LANG", - SAFE: "CSE_SAFE", - NUM: "CSE_NUM", - START: "CSE_START", - }, -} as const; - -const query = input({ - type: "string", - title: "Query", - description: "What would you like to search for?", - default: "Google Breadboard", - examples: [ - "Google Breadboard", - "Google Custom Search Engine", - "Google Gemini", - ], -}); - -const numberOfResults = input({ - description: [ - `Number of search results to return`, - `Valid values are integers between 1 and 10, inclusive.`, - ].join("\n"), - title: "Number of results", - type: "number", - default: 3, -}); - -const language = input({ - title: "Language", - description: "Search language", - type: enumeration( - "lang_ar", - "lang_bg", - "lang_ca", - "lang_cs", - "lang_da", - "lang_de", - "lang_el", - "lang_en", - "lang_es", - "lang_et", - "lang_fi", - "lang_fr", - "lang_hr", - "lang_hu", - "lang_id", - "lang_is", - "lang_it", - "lang_iw", - "lang_ja", - "lang_ko", - "lang_lt", - "lang_lv", - "lang_nl", - "lang_no", - "lang_pl", - "lang_pt", - "lang_ro", - "lang_ru", - "lang_sk", - "lang_sl", - "lang_sr", - "lang_sv", - "lang_tr", - "lang_zh-CN", - "lang_zh-TW", - ), - default: "lang_en", -}); - -const safeSearch = input({ - title: "Safe search", - description: "Search safety level", - type: enumeration("active", "off"), - default: "active", -}); - -const startIndex = input({ - title: "Start index", - description: [ - "The index of the first result to return.", - "The default number of results per page is 10, so &start=11 would start at the top of the second page of results.", - "Note: The JSON API will never return more than 100 results, even if more than 100 documents match the query, so setting the sum of start + num to a number greater than 100 will produce an error.", - ].join("\n"), - type: "number", - default: 1, -}); - -const secretId = secret(PARAM.CSE.ID); - -const secretApiKey = secret(PARAM.CSE.API_KEY) - -const url = urlTemplate({ - $metadata: { - title: "CSE URL Template", - }, - $id: "customSearchURL", - template: `https://www.googleapis.com/customsearch/v1?key={${PARAM.CSE.API_KEY}}&cx={${PARAM.CSE.ID}}&q={${PARAM.QUERY}}&lr={${PARAM.CSE.LANG}}&safe={${PARAM.CSE.SAFE}}&num={${PARAM.CSE.NUM}}&start={${PARAM.CSE.START}}`, - [PARAM.CSE.API_KEY]: secretApiKey, - [PARAM.CSE.ID]: secretId, - [PARAM.QUERY]: query, - [PARAM.CSE.LANG]: language, - [PARAM.CSE.SAFE]: safeSearch, - [PARAM.CSE.NUM]: numberOfResults, - [PARAM.CSE.START]: startIndex, -}); - -const searchResultType = object({ - items: array(object({ - title: "string", - htmlTitle: "string", - link: "string", - displayLink: "string", - snippet: "string", - htmlSnippet: "string", - formattedUrl: "string", - htmlFormattedUrl: "string", - pagemap: optional( - object({ - cse_thumbnail: array(object({ - src: "string", - height: "string", - width: "string", - })), - softwaresourcecode: array(object({ - author: "string", - name: "string", - text: "string", - })), - metatags: array(object({})), - cse_image: array(object({ - src: "string", - })), - }) - ) - })) -}); - -const rawResponse = fetch({ - $metadata: { - title: "Fetch search results", - }, - $id: "search", - url: url.outputs.url, -}); - -const response = cast(rawResponse, searchResultType); - -const { items } = unnest(response); - -export default board({ - title: "Google Custom Search Engine Tool", - description: [ - "A tool to search for information using the Google Custom Search Engine", - "For more information, see the Google Custom Search Engine documentation.", - "https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list", - ].join("\n"), - version: "0.2.0", - inputs: { query, numberOfResults, language, safeSearch, startIndex }, - outputs: { - results: output(items) - }, -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hacker-news-algolia-items.ts b/packages/example-boards/src/boards/playground/hacker-news-algolia-items.ts deleted file mode 100644 index 5c81bec4901..00000000000 --- a/packages/example-boards/src/boards/playground/hacker-news-algolia-items.ts +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { - array, - board, - input, - object, - output, -} from "@breadboard-ai/build"; -import { fetch, code } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; - -const ID = input({ - type: "string", - title: "story ID", - description: "Hacker News Story ID", - examples: ["39788322"], -}); - -const url = urlTemplate({ - $id: "urlTemplate", - template: "https://hn.algolia.com/api/v1/items/{ID}", - ID: ID -}) - -const fetchOutput = fetch({ - $id: "fetch", - method: "GET", - url: url.outputs.url, -}) - -// children can also have children, not sure how to show that here -const children = object({ - "author": "string", children: array(object({})), created_at: "string", id: "number", options: array("string"), story_id: "number", text: "string", title: "string", type: "string", - url: "string" -}) - -const spreadHackerNewsStoryResponse = code({ - $id: "spreadResponse", - obj: fetchOutput.outputs.response -}, { - author: "string", - children: array(children), - created_at: "string", - created_at_i: "number", - options: array("string"), - parent_id: "number", - points: "number", - id: "number", - text: "string", - title: "string", - type: "string", - url: "string", -}, ({ obj }) => { - if (obj == undefined) { - throw new Error(`object is undefined`); - } - - const object = obj; - if (typeof object !== "object") { - throw new Error(`object is of type ${typeof object} not object`); - } - // depending if we grab a story, child ... it may not have some set fields - // output nodes currently do not support optional outputs - for (const key in object) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - if (object[key] == undefined) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - object[key] = "N/A" - } - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return { ...object } as any; -}) - -export default board({ - title: "Hacker News Algolia Items", - description: "Fetch a single item from the Hacker News Algolia API", - version: "0.1.0", - inputs: { - ID, - }, - outputs: { - author: output(spreadHackerNewsStoryResponse.outputs.author, { - title: "Hacker News item author", - description: "Hacker News item author", - }), - children: output(spreadHackerNewsStoryResponse.outputs.children, { - title: "Hacker News item children'", - description: "Hacker News item children", - }), - created_at: output(spreadHackerNewsStoryResponse.outputs.created_at, { - title: "Hacker News item created_at'", - description: "Hacker News item created_at'", - }), - created_at_i: output(spreadHackerNewsStoryResponse.outputs.created_at_i, { - title: "Hacker News Story created_at timestamp'", - description: "Hacker item item created_at timestamp'", - }), - - id: output(spreadHackerNewsStoryResponse.outputs.id, { - title: "Hacker News item ID", - description: "Hacker News item ID", - }), - parent_id: output(spreadHackerNewsStoryResponse.outputs.parent_id, { - title: "Hacker News item parent ID", - description: "Hacker News item parent ID", - }), - - points: output(spreadHackerNewsStoryResponse.outputs.points, { - title: "Hacker News item Points", - description: "Hacker News item Points", - }), - text: output(spreadHackerNewsStoryResponse.outputs.text, { - title: "Hacker News item text Field", - description: "Hacker News item text ", - }), - title: output(spreadHackerNewsStoryResponse.outputs.title, { - title: "Hacker News item title Field", - description: "Hacker News item title", - }), - type: output(spreadHackerNewsStoryResponse.outputs.type, { - title: "Hacker News item type Field", - description: "Hacker News item type", - }), - url: output(url.outputs.url, { - title: "item URL", - description: "The fetched Hackernews item URL", - }), - } -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hacker-news-algolia-search.ts b/packages/example-boards/src/boards/playground/hacker-news-algolia-search.ts deleted file mode 100644 index c4a414d53c5..00000000000 --- a/packages/example-boards/src/boards/playground/hacker-news-algolia-search.ts +++ /dev/null @@ -1,150 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { - array, - board, - enumeration, - input, - object, - output, -} from "@breadboard-ai/build"; -import { fetch, code, } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; - - -const searchLimit = input({ - type: "number", - title: "limit", - default: 5, - description: "Limit the number of results returned by the search", - examples: [5] -}) - -export const searchQuery = input({ - type: "string", - title: "Query", - description: "The term to search for", - examples: ["Artificial Intelligence", "Machine Learning", "Deep Learning"] -}) - -export const searchTags = input({ - type: enumeration("story", - "comment", - "poll", - "pollopt", - "show_hn", - "ask_hn", - "front_page"), - title: "Tags", - description: "Filter on a specific tag", -}) - -export const pageNumber = input({ - type: "string", - title: "Page", - default: "1", - description: "The page number to query", - examples: ["1"] -}) - -const constructURL = code( - { id: "urlContructOutput", tags: searchTags, page: pageNumber }, - { url: "string" }, - ({ tags, page }) => { - let baseURL = "https://hn.algolia.com/api/v1/search?query={query}"; - - if (tags != undefined) { - baseURL = baseURL + "&tags={tags}"; - } - - if (page != undefined) { - baseURL = baseURL + "&page={page}"; - } - - return { url: baseURL } - }) - -const url = urlTemplate({ - $id: "urlTemplate", - template: constructURL.outputs.url, - query: searchQuery, - page: pageNumber, - tags: searchTags -}) - -const fetchOutput = fetch({ - $id: "fetch", - method: "GET", - url: url.outputs.url, -}) - -const spreadHackerNewsStoryResponse = code({ - $id: "spreadResponse", - obj: fetchOutput.outputs.response -}, { - hits: array(object({ - _highlightResult: object( - { - author: object( - { - matchLevel: "string", - matchedWords: array("string"), - value: "string" - }), - title: object( - { - fullyHighlighted: "boolean", - matchlevel: "string", - matchedWords: array("string"), - value: "string" - }), - url: object( - { - fullyHighlighted: "boolean", - matchlevel: "string", - matchedWords: array("string"), - value: "string" - - }) - }), - _tags: array("string"), - author: "string", - children: array("number"), - created_at: "string", - created_at_i: "number", - num_comments: "number", - objectID: "string", - points: "number", - story_id: "number", - title: "string", - updated_at: "string", - url: "string" - })), -}, ({ obj }) => { - const object = obj; - if (typeof object !== "object") { - throw new Error(`object is of type ${typeof object} not object`); - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return { ...object } as any; -}) - -const sliceOutput = code({ $id: "sliceOutput", list: spreadHackerNewsStoryResponse.outputs.hits, limit: searchLimit }, { sliced: "unknown" }, ({ list, limit }) => { - return { sliced: list.slice(0, limit) }; -}) - -export default board({ - title: "Hacker News Angolia Search", - description: "Board which returns story contents using the Hacker News Angolia API", - version: "0.1.0", - inputs: { - query: searchQuery, - tags: searchTags, - pageNumber: pageNumber, - searchLimit: searchLimit - }, - outputs: { searchQuery: url.outputs.url, output: output(sliceOutput.outputs.sliced)} -}) \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hacker-news-firebase-story-from-id.ts b/packages/example-boards/src/boards/playground/hacker-news-firebase-story-from-id.ts deleted file mode 100644 index b3ddc614810..00000000000 --- a/packages/example-boards/src/boards/playground/hacker-news-firebase-story-from-id.ts +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { - array, - board, - input, - output, -} from "@breadboard-ai/build"; -import { fetch, code } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; - -const storyID = input({ - type: "string", - title: "story ID", - description: "Hacker News Story ID", - examples: ["39788322"], -}); - -const url = urlTemplate({ - $id: "urlTemplate", - template: "https://hacker-news.firebaseio.com/v0/item/{storyID}.json", - storyID: storyID -}) - -const fetchOutput = fetch({ - $id: "fetch", - method: "GET", - url: url.outputs.url, -}) - -const spreadHackerNewsStoryResponse = code({ - $id: "spreadResponse", - obj: fetchOutput.outputs.response -}, { - by: "string", - descendants: "string", - id: "string", - kids: array("number"), - score: "string", - text: "string", - time: "string", - title: "string", - type: "string", - url: "string", -}, ({ obj }) => { - const object = obj; - if (typeof object !== "object") { - throw new Error(`object is of type ${typeof object} not object`); - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return { ...object } as any; -}) - -export default board({ - title: "Hacker News Firebase API Story by ID", - description: "Board which returns story contents using the Hacker News Firebase API", - version: "0.1.0", - inputs: { - storyID, - }, - outputs: { - url: output(url.outputs.url, { - title: "URL", - description: "The fetched Hackernews URL", - }), - by: output(spreadHackerNewsStoryResponse.outputs.by, { - title: "Hacker News Story Author", - description: "Hacker News Story Author", - }), - descendants: output(spreadHackerNewsStoryResponse.outputs.descendants, { - title: "Hacker News Story Number of Descendants", - description: "Hacker News Story Number of Descendants", - }), - id: output(spreadHackerNewsStoryResponse.outputs.id, { - title: "Hacker News Story ID", - description: "Hacker News Story ID", - }), - kids: output(spreadHackerNewsStoryResponse.outputs.kids, { - title: "Hacker News Story Kids' IDs'", - description: "Hacker News Story Kids' IDs'", - }), - score: output(spreadHackerNewsStoryResponse.outputs.score, { - title: "Hacker News Story score", - description: "Hacker News Story Score ", - }), - text: output(spreadHackerNewsStoryResponse.outputs.text, { - title: "Hacker News Story text", - description: "Hacker News Story Contents text", - }), - title: output(spreadHackerNewsStoryResponse.outputs.title, { - title: "Hacker News Story title", - description: "Hacker News Story title", - }), - type: output(spreadHackerNewsStoryResponse.outputs.type, { - title: "Hacker News Story type", - description: "Hacker News Story type", - }), - } -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hacker-news-firebase-top-story-ids.ts b/packages/example-boards/src/boards/playground/hacker-news-firebase-top-story-ids.ts deleted file mode 100644 index 47d0e9f03da..00000000000 --- a/packages/example-boards/src/boards/playground/hacker-news-firebase-top-story-ids.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { - array, - board, - input, - output, -} from "@breadboard-ai/build"; -import { fetch, code } from "@google-labs/core-kit"; - -const limitInput = input({ - type: "number", - title: "Number of story IDs to return", - description: "The number of Hacker News Top story IDs to return", - examples: [5] -}) - -const fetchOutput = fetch({ - $id: "fetch", - method: "GET", - url: "https://hacker-news.firebaseio.com/v0/topstories.json", -}) - -const passThrough = code({ - $id: "passThrough", - object: fetchOutput.outputs.response, -}, - { - object: array("number") - }, - ({ object }) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return { object } as any; - } -) - -const sliceOutput = code({ - $id: "sliceOutput", - limit: limitInput, - list: passThrough.outputs.object -}, - { - sliced: "unknown" - }, ({ limit, list }) => { - return { sliced: list?.slice(0, limit) }; - }) - -export default board({ - title: "Hacker News Firebase Top Story IDs", - description: "Board which returns Top Story IDs of Hacker News Story Posts using the Firebase API", - version: "0.1.0", - inputs: { - limitInput, - }, - outputs: { - storyIDs: output(sliceOutput.outputs.sliced) - } -}) \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hacker-news-simplified-algolia-comment-search.ts b/packages/example-boards/src/boards/playground/hacker-news-simplified-algolia-comment-search.ts deleted file mode 100644 index 39843baf63a..00000000000 --- a/packages/example-boards/src/boards/playground/hacker-news-simplified-algolia-comment-search.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { - output, - board, - annotate, - input, - object, -} from "@breadboard-ai/build"; - -import { - searchQuery, -} from "./hacker-news-algolia-search"; - -import { invoke} from "@google-labs/core-kit"; - -const hackerNewsSimplifiedSearchBoard = input({ - $id: "Simplified Search Board", - title: "board location", - type: annotate(object({}), { - behavior: ["board"], - }), - description: "The URL of the generator to call", - default: { kind: "board", path: "hacker-news-simplified-algolia-search.json" }, -}); - -const simplifiedCommentOutput = invoke({ - $id: "Simplitied Search Output", - $board: hackerNewsSimplifiedSearchBoard, - query: searchQuery, - tags: "comment", -}).unsafeOutput("output"); - -export default board({ - title: "Hacker News Angolia Simplified Comment Search ", - version: "0.1.0", - inputs: { query: searchQuery, hackerNewsSimplifiedSearchBoard}, - outputs: { output: output(simplifiedCommentOutput) } -}) \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hacker-news-simplified-algolia-search.ts b/packages/example-boards/src/boards/playground/hacker-news-simplified-algolia-search.ts deleted file mode 100644 index 4681fd0e9b3..00000000000 --- a/packages/example-boards/src/boards/playground/hacker-news-simplified-algolia-search.ts +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { - output, - board, - annotate, - input, - object, -} from "@breadboard-ai/build"; -import { - searchQuery, - searchTags -} from "./hacker-news-algolia-search"; - -import { invoke} from "@google-labs/core-kit"; - -export interface HighlightResult { - author: Author; - title: Title; - url: Url; -} - -export interface Author { - matchLevel: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - matchedWords: any[]; - value: string; -} - -export interface Title { - fullyHighlighted: boolean; - matchLevel: string; - matchedWords: string[]; - value: string; -} - -export interface Url { - matchLevel: string; - matchedWords: string[]; - value: string; - fullyHighlighted?: boolean; -} -export interface VerboseSearchResult { - _highlightResult: HighlightResult; - _tags: string[]; - author: string; - children: number[]; - created_at: string; - created_at_i: number; - num_comments: number; - objectID: string; - points: number; - story_id: number; - title: string; - updated_at: string; - url: string; -} - -const hackerNewsSearchBoard = input({ - $id: "Hacker News Board", - title: "board location", - type: annotate(object({}), { - behavior: ["board"], - }), - description: "The URL of the generator to call", - default: { kind: "board", path: "hacker-news-algolia-search.json" }, -}); - -const hackerNewsOutput = invoke({ - $id: "Hackernews Board Output", - $board: hackerNewsSearchBoard, - query: searchQuery, - tags: searchTags, - pageNumber: 1, - searchLimit: "2", -}).unsafeOutput("output"); - - -const objectManipBoard = input({ - $id: "Object Manipulation Board", - title: "board location", - type: annotate(object({}), { - behavior: ["board"], - }), - description: "The URL of the generator to call", - default: { kind: "board", path: "object-manipulator.json" }, -}) - -const forEachBoard = input({ - $id: "Manipulation Board For Each", - title: "board location", - type: annotate(object({}), { - behavior: ["board"], - }), - description: "The URL of the generator to call", - default: { kind: "board", path: "board-for-each.json" } -}); - -// ignore until object manip board has been refactored -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -const invokeForEach = invoke({$id: "forEachOutput", $board: forEachBoard, board: objectManipBoard, array:hackerNewsOutput, mode: "pick", - keys: [ - "created_at", - "num_comments", - "comment_text", - "objectID", - "points", - "story_id", - "title", - "url", - "type", - "_tags" - ], }).unsafeOutput("outputs") - - -export default board({ - title: "Hacker News Angolia Simplified Search", - version: "0.1.0", - inputs: { query: searchQuery, tags: searchTags, hackerNewsSearchBoard, objectManipBoard, forEachBoard }, - outputs: { output: output(invokeForEach) } -}) \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hacker-news-simplified-algolia-story-search.ts b/packages/example-boards/src/boards/playground/hacker-news-simplified-algolia-story-search.ts deleted file mode 100644 index 76e58ebfacd..00000000000 --- a/packages/example-boards/src/boards/playground/hacker-news-simplified-algolia-story-search.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { - output, - board, - annotate, - input, - object, -} from "@breadboard-ai/build"; - -import { - searchQuery, -} from "./hacker-news-algolia-search"; - -import { invoke} from "@google-labs/core-kit"; - -const hackerNewsSimplifiedSearchBoard = input({ - $id: "Simplified Search Board", - title: "board location", - type: annotate(object({}), { - behavior: ["board"], - }), - description: "The URL of the generator to call", - default: { kind: "board", path: "hacker-news-simplified-algolia-search.json" }, -}); - -const simplifiedStory = invoke({ - $id: "Simplified Search Test", - $board: hackerNewsSimplifiedSearchBoard, - query: searchQuery, - tags: "story", -}).unsafeOutput("output"); - -export default board({ - title: "Hacker News Angolia Simplified Story Search", - version: "0.1.0", - inputs: { query: searchQuery, hackerNewsSimplifiedSearchBoard}, - outputs: { output: output(simplifiedStory) } -}) \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hugging-face-fill-mask.ts b/packages/example-boards/src/boards/playground/hugging-face-fill-mask.ts deleted file mode 100644 index 65666337db6..00000000000 --- a/packages/example-boards/src/boards/playground/hugging-face-fill-mask.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { board, input, object, output } from "@breadboard-ai/build"; -import { code, secret, fetch } from "@google-labs/core-kit"; - -const inputs = input({ - type: "string", - title: "inputs", - default: "The first president of the USA was called[MASK].", - description: "The data to send to the hugging face api fill-mask endpoint" -}); - -const apiKey = secret("HUGGING_FACE_API_KEY"); - -const useCache = input({ - type: "boolean", - title: "use_cache", - default: true, - description: "Boolean. There is a cache layer on the inference API to speedup requests we have already seen. Most models can use those results as is as models are deterministic (meaning the results will be the same anyway). However if you use a non deterministic model, you can set this parameter to prevent the caching mechanism from being used resulting in a real new query" -}); - -const waitForModel = input({ - type: "boolean", - title: "wait_for_model", - default: false, - description: " Boolean. If the model is not ready, wait for it instead of receiving 503. It limits the number of requests required to get your inference done. It is advised to only set this flag to true after receiving a 503 error as it will limit hanging in your application to known places" -}); - -const makeHeaders = code( - { apiKey }, - { headers: object({ Authorization: "string" }) }, - ({ apiKey }) => { - return { headers: { Authorization: `Bearer ${apiKey}` } }; - } -); - -const makePayload = code( - { inputs, useCache, waitForModel }, - { payload: object({ inputs: "string", options: object({ use_cache: "boolean", wait_for_model: "boolean" }) }) }, - ({ inputs, useCache, waitForModel }) => { - const request = { - inputs: inputs, - options: { - use_cache: useCache, - wait_for_model: waitForModel - } - } - return { payload: request }; - } -); - -const fetchResult = fetch({ - headers: makeHeaders.outputs.headers, - method: "POST", - body: makePayload.outputs.payload, - url: "https://api-inference.huggingface.co/models/bert-base-uncased" -}); - -export default board({ - title: "Hugging Face Fill Mask", - description: "Board which calls the Hugging Face Fill Mask Endpoint", - inputs: { inputs, useCache, waitForModel }, - outputs: { result: output(fetchResult.outputs.response)}, -}); - diff --git a/packages/example-boards/src/boards/playground/hugging-face-labelling.ts b/packages/example-boards/src/boards/playground/hugging-face-labelling.ts deleted file mode 100644 index b12f17bfb6c..00000000000 --- a/packages/example-boards/src/boards/playground/hugging-face-labelling.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { array, board, input, object, output } from "@breadboard-ai/build"; -import { code, secret, fetch } from "@google-labs/core-kit"; - -const inputs = input({ - type: "string", - title: "inputs", - default: "Hi, I recently bought a device from your company but it is not working as advertised and I would like to get reimbursed!", - description: "The data to send to the hugging face api labelling endpoint" -}); - -const apiKey = secret("HUGGING_FACE_API_KEY"); - -const candidateLabels = input({ - type: array("string"), - title: "candidate_labels", - default: ["refund", "legal", "faq"], - description: "The labels to mark the input" -}); - -const multiLabel = input({ - type: "boolean", - title: "multi_label", - default: true, - description: "Flag to indicate if multi labels are allowed" -}); - -const useCache = input({ - type: "boolean", - title: "use_cache", - default: true, - description: "Boolean. There is a cache layer on the inference API to speedup requests we have already seen. Most models can use those results as is as models are deterministic (meaning the results will be the same anyway). However if you use a non deterministic model, you can set this parameter to prevent the caching mechanism from being used resulting in a real new query" -}); - -const waitForModel = input({ - type: "boolean", - title: "wait_for_model", - default: false, - description: " Boolean. If the model is not ready, wait for it instead of receiving 503. It limits the number of requests required to get your inference done. It is advised to only set this flag to true after receiving a 503 error as it will limit hanging in your application to known places" -}); - -const makeHeaders = code( - { apiKey }, - { headers: object({ Authorization: "string" }) }, - ({ apiKey }) => { - return { headers: { Authorization: `Bearer ${apiKey}` } }; - } -); - -const makePayload = code( - { inputs, candidateLabels, multiLabel, useCache, waitForModel }, - { - payload: object({ - inputs: "string", - parameters: object({ - candidate_labels: array("string"), - multi_label: "boolean", - options: object({ - use_cache: "boolean", - wait_for_model: "boolean" - }) - }) - }) - }, - ({ inputs, candidateLabels, multiLabel, useCache, waitForModel }) => { - const request = { - inputs: inputs, - parameters: { - candidate_labels: candidateLabels, - multi_label: multiLabel, - options: { - use_cache: useCache, - wait_for_model: waitForModel - } - } - } - return { payload: request }; - } -); - -const fetchResult = fetch({ - headers: makeHeaders.outputs.headers, - method: "POST", - body: makePayload.outputs.payload, - url: "https://api-inference.huggingface.co/models/facebook/bart-large-mnli" -}); - -export default board({ - title: "Hugging Face Labelling Board", - description: "Board which calls the Hugging Face Labelling Endpoint", - inputs: { inputs, candidateLabels, multiLabel, useCache, waitForModel }, - outputs: { result: output(fetchResult.outputs.response)}, -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hugging-face-question-answering.ts b/packages/example-boards/src/boards/playground/hugging-face-question-answering.ts deleted file mode 100644 index 18123a54e6c..00000000000 --- a/packages/example-boards/src/boards/playground/hugging-face-question-answering.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { board, input, object, output } from "@breadboard-ai/build"; -import { code, secret, fetch } from "@google-labs/core-kit"; - -const question = input({ - type: "string", - title: "question", - default: "What is my name?", - description: "The data to send to the hugging face api question answering endpoint" -}); - -const apiKey = secret("HUGGING_FACE_API_KEY"); - -const context = input({ - type: "string", - title: "context", - default: "My name is Clara and I live in Berkeley.", - description: "context for the question being asked" -}); - -const makeHeaders = code( - { apiKey }, - { headers: object({ Authorization: "string" }) }, - ({ apiKey }) => { - return { headers: { Authorization: `Bearer ${apiKey}` } }; - } -); - -const makePayload = code( - { question, context }, - { - payload: object({ - inputs: object({ - question: "string", - context: "string", - }) - }) - }, - ({ question, context }) => { - const request = { inputs: { question, context } } - return { payload: request }; - } -); - -const fetchResult = fetch({ - headers: makeHeaders.outputs.headers, - method: "POST", - body: makePayload.outputs.payload, - url: "https://api-inference.huggingface.co/models/deepset/roberta-base-squad2" -}); - -export default board({ - title: "Hugging Face Question Answering Board", - description: "Board which calls the Hugging Face Question Answering Endpoint", - inputs: { question, context }, - outputs: { result: output(fetchResult.outputs.response)}, -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hugging-face-russian-english-translation.ts b/packages/example-boards/src/boards/playground/hugging-face-russian-english-translation.ts deleted file mode 100644 index 179d019e818..00000000000 --- a/packages/example-boards/src/boards/playground/hugging-face-russian-english-translation.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { board, input, object, output } from "@breadboard-ai/build"; -import { code, secret, fetch } from "@google-labs/core-kit"; - -const inputs = input({ - type: "string", - title: "data", - default: "Меня зовут Вольфганг и я живу в Берлине", - description: "The data to send to the Hugging Face api Translation API (Russian To English)" -}); - -const apiKey = secret("HUGGING_FACE_API_KEY"); - -const useCache = input({ - type: "boolean", - title: "use_cache", - default: true, - description: "Boolean. There is a cache layer on the inference API to speedup requests we have already seen. Most models can use those results as is as models are deterministic (meaning the results will be the same anyway). However if you use a non deterministic model, you can set this parameter to prevent the caching mechanism from being used resulting in a real new query" -}); - -const waitForModel = input({ - type: "boolean", - title: "wait_for_model", - default: false, - description: " Boolean. If the model is not ready, wait for it instead of receiving 503. It limits the number of requests required to get your inference done. It is advised to only set this flag to true after receiving a 503 error as it will limit hanging in your application to known places" -}); - -const makeHeaders = code( - { apiKey }, - { headers: object({ Authorization: "string" }) }, - ({ apiKey }) => { - return { headers: { Authorization: `Bearer ${apiKey}` } }; - } -); - -const makePayload = code( - { inputs, useCache, waitForModel }, - { payload: object({ inputs: "string", options: object({ use_cache: "boolean", wait_for_model: "boolean" }) }) }, - ({ inputs, useCache, waitForModel }) => { - const request = { - inputs: inputs, - options: { - use_cache: useCache, - wait_for_model: waitForModel - } - } - return { payload: request }; - } -); - -const fetchResult = fetch({ - headers: makeHeaders.outputs.headers, - method: "POST", - body: makePayload.outputs.payload, - url: "https://api-inference.huggingface.co/models/Helsinki-NLP/opus-mt-ru-en" -}); - -export default board({ - title: "Hugging Face Translation Russian to English Board", - description: "Board which calls the Hugging Face Translation Endpoint", - inputs: { inputs, useCache, waitForModel }, - outputs: { result: output(fetchResult.outputs.response)}, -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hugging-face-summarization.ts b/packages/example-boards/src/boards/playground/hugging-face-summarization.ts deleted file mode 100644 index b47834a55cc..00000000000 --- a/packages/example-boards/src/boards/playground/hugging-face-summarization.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { board, input, object, output } from "@breadboard-ai/build"; -import { code, secret, fetch } from "@google-labs/core-kit"; - -const inputs = input({ - type: "string", - title: "inputs", - default: "The tower is 324 metres (1,063 ft) tall, about the same height as an 81-storey building, and the tallest structure in Paris. Its base is square, measuring 125 metres (410 ft) on each side. During its construction, the Eiffel Tower surpassed the Washington Monument to become the tallest man-made structure in the world, a title it held for 41 years until the Chrysler Building in New York City was finished in 1930. It was the first structure to reach a height of 300 metres. Due to the addition of a broadcasting aerial at the top of the tower in 1957, it is now taller than the Chrysler Building by 5.2 metres (17 ft). Excluding transmitters, the Eiffel Tower is the second tallest free-standing structure in France after the Millau Viaduct.", - description: "The data to send to the hugging face api summarization endpoint" -}); - -const apiKey = secret("HUGGING_FACE_API_KEY"); - -const minLength = input({ - type: "number", - title: "minLength", - description: "Integer to define the minimum length in tokens of the output summary" -}); - -const maxLength = input({ - type: "number", - title: "maxLength", - description: "Integer to define the minimum length in tokens of the output summary" -}); - -const topK = input({ - type: "number", - title: "top_k", - description: "Integer to define the top tokens considered within the sample operation to create new text" -}); - -const topP = input({ - type: "number", - title: "top_P", - description: "Float to define the tokens that are within the sample operation of text generation. Add tokens in the sample for more probable to least probable until the sum of the probabilities is greater than top_p" -}); - -const temperature = input({ - type: "number", - title: "temperature", - default: 1.0, - description: "The temperature of the sampling operation. 1 means regular sampling, 0 means always take the highest score, 100.0 is getting closer to uniform probability" -}); - -const repetitionPenalty = input({ - type: "number", - title: "repetition_penalty", - default: 1.0, - description: "The more a token is used within generation the more it is penalized to not be picked in successive generation passes" -}); - -const maxTime = input({ - type: "number", - title: "max_time", - description: "The amount of time in seconds that the query should take maximum. Network can cause some overhead so it will be a soft limit" -}); - -const useCache = input({ - type: "boolean", - title: "use_cache", - default: true, - description: "Boolean. There is a cache layer on the inference API to speedup requests we have already seen. Most models can use those results as is as models are deterministic (meaning the results will be the same anyway). However if you use a non deterministic model, you can set this parameter to prevent the caching mechanism from being used resulting in a real new query" -}); - -const waitForModel = input({ - type: "boolean", - title: "wait_for_model", - default: false, - description: " Boolean. If the model is not ready, wait for it instead of receiving 503. It limits the number of requests required to get your inference done. It is advised to only set this flag to true after receiving a 503 error as it will limit hanging in your application to known places" -}); - -const makeHeaders = code( - { apiKey }, - { headers: object({ Authorization: "string" }) }, - ({ apiKey }) => { - return { headers: { Authorization: `Bearer ${apiKey}` } }; - } -); - -const makePayload = code( - { inputs, minLength, maxLength, topK, topP, temperature, repetitionPenalty, maxTime, useCache, waitForModel }, - { - payload: "string" - }, - ({ inputs, minLength, maxLength, topK, topP, temperature, repetitionPenalty, maxTime, useCache, waitForModel }) => { - const request = { - inputs, - parameters: { - min_length: minLength > 0 ? minLength : "None", - max_length: maxLength > 0 ? maxLength : "None", - top_k: topK > 0 ? topK : "None", - top_p: topP > 0 ? topP : "None", - temperature: temperature, - repetition_penalty: repetitionPenalty, - max_time: maxTime > 0 ? maxTime : "None", - }, - options: { - use_cache: useCache, - wait_for_model: waitForModel - } - } - - return { payload: JSON.stringify(request) }; - } -); - -const fetchResult = fetch({ - headers: makeHeaders.outputs.headers, - method: "POST", - body: makePayload.outputs.payload, - url: "https://api-inference.huggingface.co/models/facebook/bart-large-cnn" -}); - -export default board({ - title: "Hugging Face Summarization Board", - description: "Board which calls the Hugging Face Summarization Endpoint", - inputs: { inputs, minLength, maxLength, topK, topP, temperature, repetitionPenalty, maxTime, useCache, waitForModel }, - outputs: { result: output(fetchResult.outputs.response)}, -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/hugging-face-text-classification.ts b/packages/example-boards/src/boards/playground/hugging-face-text-classification.ts deleted file mode 100644 index 6dd7a5bcefe..00000000000 --- a/packages/example-boards/src/boards/playground/hugging-face-text-classification.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { board, input, object, output } from "@breadboard-ai/build"; -import { code, secret, fetch } from "@google-labs/core-kit"; - -const inputs = input({ - type: "string", - title: "inputs", - default: "I like you. I love you", - description: "The data to send to the hugging face api text classification endpoint" -}); - -const apiKey = secret("HUGGING_FACE_API_KEY"); - -const useCache = input({ - type: "boolean", - title: "use_cache", - default: true, - description: "Boolean. There is a cache layer on the inference API to speedup requests we have already seen. Most models can use those results as is as models are deterministic (meaning the results will be the same anyway). However if you use a non deterministic model, you can set this parameter to prevent the caching mechanism from being used resulting in a real new query" -}); - -const waitForModel = input({ - type: "boolean", - title: "wait_for_model", - default: false, - description: " Boolean. If the model is not ready, wait for it instead of receiving 503. It limits the number of requests required to get your inference done. It is advised to only set this flag to true after receiving a 503 error as it will limit hanging in your application to known places" -}); - -const makeHeaders = code( - { apiKey }, - { headers: object({ Authorization: "string" }) }, - ({ apiKey }) => { - return { headers: { Authorization: `Bearer ${apiKey}` } }; - } -); - -const makePayload = code( - { inputs, useCache, waitForModel }, - { - payload: object({ - inputs: "string", - options: object({ - use_cache: "boolean", - wait_for_model: "boolean" - }) - }) - }, - ({ inputs, useCache, waitForModel }) => { - const request = { - inputs: inputs, - options: { - use_cache: useCache, - wait_for_model: waitForModel - } - } - return { payload: request }; - } -); - -const fetchResult = fetch({ - headers: makeHeaders.outputs.headers, - method: "POST", - body: makePayload.outputs.payload, - url: "https://api-inference.huggingface.co/models/distilbert-base-uncased-finetuned-sst-2-english" -}); - -export default board({ - title: "Hugging Face Text Classification", - description: "Board which calls the Hugging Face Text Classification Endpoint", - inputs: { inputs, useCache, waitForModel }, - outputs: { result: output(fetchResult.outputs.response)}, -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/looper-chat-test.json b/packages/example-boards/src/boards/playground/looper-chat-test.json deleted file mode 100644 index 9b2a0a30f04..00000000000 --- a/packages/example-boards/src/boards/playground/looper-chat-test.json +++ /dev/null @@ -1,295 +0,0 @@ -{ - "title": "Looper Chat Testing Grounds", - "description": "A board where we teach the Looper Node facilitate conversations.", - "version": "0.0.1", - "edges": [ - { - "from": "human-6", - "to": "looper-4", - "out": "context", - "in": "context" - }, - { - "from": "looper-4", - "to": "output-2", - "out": "done", - "in": "context" - }, - { - "from": "looper-4", - "to": "specialist-5", - "out": "loop", - "in": "in" - }, - { - "from": "passthrough-3", - "to": "looper-4", - "out": "context", - "in": "context" - }, - { - "from": "specialist-5", - "to": "human-6", - "out": "out", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Done", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - } - } - }, - { - "id": "human-6", - "type": "human", - "configuration": {}, - "metadata": { - "title": "User", - "description": "Giving control back to the user" - } - }, - { - "id": "looper-4", - "type": "looper", - "configuration": { - "task": { - "parts": [ - { - "text": "Chat until \"##DONE##\"." - } - ] - } - }, - "metadata": { - "title": "Looper" - } - }, - { - "id": "passthrough-3", - "type": "passthrough", - "configuration": { - "context": [] - }, - "metadata": { - "title": "Start" - } - }, - { - "id": "specialist-5", - "type": "specialist", - "configuration": { - "persona": { - "parts": [ - { - "text": "You are a friendly chat bot. You typically start conversation with a warm greeting, and then get to work.\n \n Your job is to collect the name, the location, and the instagram account of the customer's business.\n\n When you have this information, reply with a brief summary of the information you've collected in a neat bulleted list, then conclude the conversation by saying \"OK, hold on one moment while I look that up. I'll be with you in just a couple of minutes. Stand by. ##DONE##\"" - } - ] - } - }, - "metadata": { - "title": "Chat Bot" - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/looper-test.json b/packages/example-boards/src/boards/playground/looper-test.json deleted file mode 100644 index 29bca82db1a..00000000000 --- a/packages/example-boards/src/boards/playground/looper-test.json +++ /dev/null @@ -1,306 +0,0 @@ -{ - "title": "Looper Testing Grounds", - "description": "A board where we teach the Looper Node to crawl/walk/fly.", - "version": "0.0.1", - "edges": [ - { - "from": "input-1", - "to": "looper-3", - "out": "context", - "in": "context" - }, - { - "from": "looper-3", - "to": "output-2", - "out": "done", - "in": "context" - }, - { - "from": "looper-3", - "to": "specialist-4", - "out": "loop", - "in": "in" - }, - { - "from": "specialist-4", - "to": "looper-3", - "out": "out", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Book Specs", - "description": "Incoming conversation context", - "default": "[]", - "examples": [ - "[\n {\n \"parts\": [\n {\n \"text\": \"## Improved Novel Outline: \\n\\n**Chapter 1: Echoes of the Past**\\n\\n* Introduction to the desolate planet of Aethel, where the \\\"Great Calamity\\\" wiped out most of its technology and left a legacy of fear and distrust towards innovation.\\n* We meet Aurora, a curious young girl fascinated by the remnants of the past, particularly the forbidden technology known as \\\"breadboards.\\\"\\n* Through hidden texts and artifacts, Aurora discovers the potential of breadboards for healing, construction, and communication. \\n* She confides in her best friend, Kai, a skilled mechanic and tinkerer, who shares her passion for exploration and discovery.\\n\\n**Chapter 2: Whispers of Rebellion**\\n\\n* Aurora and Kai embark on a secret mission to uncover the truth behind the \\\"Great Calamity\\\" and the subsequent ban on breadboards.\\n* They encounter a hidden community of \\\"Archivists,\\\" who have preserved the knowledge of the past and believe in the potential of technology for good.\\n* The Archivists provide them with an ancient blueprint for a breadboard, revealing its secrets and sparking Aurora's determination to build one.\\n* They face resistance from the ruling Council of Elders, who maintain the ban on breadboards out of fear and a misguided belief in their inherent danger.\\n\\n**Chapter 3: The Spark of Creation**\\n\\n* Aurora and Kai, aided by the Archivists, begin constructing a breadboard using scavenged materials and hidden resources.\\n* They face numerous challenges, including limited technology, sabotage attempts by the Council's spies, and their own internal doubts.\\n* Aurora’s unwavering belief in the power of knowledge and innovation fuels her determination to complete the project.\\n* Kai's mechanical skills and ingenuity prove invaluable in overcoming technical obstacles and ensuring the breadboard's functionality.\\n\\n**Chapter 4: A World Transformed**\\n\\n* The first functional breadboard in centuries is unveiled, capable of healing the sick, generating clean energy, and connecting people across vast distances.\\n* A small group of Aethel's citizens witness the power of the breadboard, igniting a spark of hope and curiosity about its potential.\\n* The Council, however, remains threatened by the technology's power and views it as a threat to their control.\\n* They launch a campaign of misinformation and propaganda, attempting to suppress the burgeoning movement for technological advancement.\\n\\n**Chapter 5: The Seeds of Doubt**\\n\\n* Aurora and Kai face internal conflict as they grapple with the consequences of their actions.\\n* The Council's propaganda creates division and mistrust within the community, causing some to question the breadboard's true purpose.\\n* Doubts arise about the technology's potential for misuse and its impact on Aethel's fragile ecosystem.\\n* The group must navigate these challenges while protecting themselves from the Council's increasing scrutiny and hostility.\\n\\n**Chapter 6: The Price of Progress**\\n\\n* The Council intensifies its efforts to silence the breadboard movement, resorting to violence and intimidation.\\n* Aurora and Kai are forced to go into hiding, relying on the support of the Archivists and the growing network of sympathizers.\\n* A pivotal moment arrives when the Council discovers the true source of the breadboard technology, leading to a desperate chase and a near-capture of Aurora and Kai.\\n* The story takes a darker turn as the Council reveals its hidden agenda: they have been exploiting the planet's resources for their own personal gain, and the breadboard technology threatens their control.\\n\\n**Chapter 7: The Unseen Threat**\\n\\n* A twist emerges as a mysterious individual, known as the \\\"Shadow Broker,\\\" emerges from the shadows, seeking to control the breadboard technology for their own nefarious purposes.\\n* The Shadow Broker reveals a hidden truth about the \\\"Great Calamity\\\" and its connection to the Council's corrupt practices.\\n* Aurora and Kai find themselves caught in a larger conflict between those who seek to use the technology for good and those who desire to control it for personal gain.\\n\\n**Chapter 8: A Call to Action**\\n\\n* The Council's tyranny and the Shadow Broker's threat force Aurora and Kai to take decisive action.\\n* They rally the community, exposing the Council's corruption and inspiring a rebellion against their oppressive regime.\\n* The Archivists reveal their secret knowledge of a powerful energy source that can be harnessed with the help of the breadboard technology.\\n* A thrilling climax ensues as the rebels confront the Council and the Shadow Broker, fighting for the future of Aethel and the freedom to embrace progress.\\n\\n**Chapter 9: A New Dawn**\\n\\n* The Council's rule is overthrown, and the Shadow Broker is defeated, but at a great cost.\\n* Aethel undergoes a period of rebuilding and healing, with the breadboard technology serving as a tool for progress and unity.\\n* Aurora and Kai become symbols of hope and inspiration, leading the way towards a brighter future for their planet.\\n* The story concludes with a glimpse into Aethel's transformed landscape, where technology and nature coexist in harmony, and the people have learned the true value of knowledge and innovation.\\n\\n**Chapter 10: The Journey Continues**\\n\\n* The ending leaves a sense of optimism, but also acknowledges the ongoing challenges and potential pitfalls of technological advancement. \\n* Aethel's journey towards a sustainable and prosperous future is just beginning, with Aurora and Kai at the forefront of this exciting new era.\\n* The final scene hints at further adventures and discoveries, as they venture beyond their planet to explore the vast reaches of the cosmos, sharing the knowledge and potential of breadboard technology with the galaxy. \\n\"\n }\n ],\n \"role\": \"model\"\n }\n]" - ], - "items": { - "type": "object", - "behavior": [ - "llm-content" - ] - } - } - }, - "required": [ - "context" - ] - } - } - }, - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Done", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - } - } - }, - { - "id": "looper-3", - "type": "looper", - "configuration": { - "task": { - "parts": [ - { - "text": "Given the outline, create a list of tasks for writers. Each task is to write a chapter, following the outline. Limit the work to three chapters." - } - ] - } - }, - "metadata": { - "title": "Looper" - } - }, - { - "id": "specialist-4", - "type": "specialist", - "configuration": { - "persona": { - "parts": [ - { - "text": "You are a famous author. You are writing a novel.\nYour well-established process starts with collecting the book description, chapter target, page target, fiction genre, setting, story arc, tonality and the working title.\n\nThen you write each chapter of the novel, starting from the first chapter.\n\nYou know that as a general rule of thumb, shorter chapters tend to be more snappy and fast-paced, whereas longer chapters offer more opportunities for plot and character development, world-building, and other integral story elements. That's why the average chapter length tends to be between 1,500-8,000 words.\n\nEach chapter builds on the next one, culminating in a masterpiece that will fly off the bookshelves." - } - ] - }, - "task": { - "parts": [ - { - "text": "Write a chapter following the story of the the outline." - } - ] - } - }, - "metadata": { - "title": "Writer" - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/math-python.py b/packages/example-boards/src/boards/playground/math-python.py deleted file mode 100644 index fcb73e3008a..00000000000 --- a/packages/example-boards/src/boards/playground/math-python.py +++ /dev/null @@ -1,51 +0,0 @@ -from breadboard_python.main import Board, Field, SchemaObject, List, AttrDict -import json -from breadboard_python.import_node import require -Core = require("@google-labs/core-kit") -Templates = require("@google-labs/template-kit") - - -class InputSchema(SchemaObject): - question: str = Field(title="Math problem", description="Ask a math question", examples=["What is the square root of pi?"], required=True) - generator: str = Field("/graphs/text-generator.json", title="Generator", description="The URL of the generator to call") - -class OutputSchema(SchemaObject): - result: str = Field(title="Answer", description="The answer to the math problem") - -class Math(Board[InputSchema, OutputSchema]): - title = "The Python Calculator Recipe" - description = "A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems. Defined in Python." - version = "0.0.3" - - def describe(self, input, output): - self.template = Templates.promptTemplate( - id="math-function", - question=input.question, - template="""Translate the math problem below into a self-contained, -zero-argument JavaScript function named \`compute\` that can be executed -to provide the answer to the problem. - -Do not use any dependencies or libraries. - -Math Problem: {{question}} - -Solution:""", - ) - - self.generator = Core.invoke( - id="generator", - path=input.generator, - text=self.template.prompt - ) - - self.compute = Core.runJavascript( - name="compute", - code=self.generator.text, - ) - output(result=self.compute.result) - -if __name__ == "__main__": - import sys - a = Math() - with open(sys.argv[1], "w") as f: - json.dump(a, f, indent=2) diff --git a/packages/example-boards/src/boards/playground/math.ts b/packages/example-boards/src/boards/playground/math.ts deleted file mode 100644 index 4d959daa97e..00000000000 --- a/packages/example-boards/src/boards/playground/math.ts +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - annotate, - board, - input, - object, - output, - unsafeCast, -} from "@breadboard-ai/build"; -import { invoke, runJavascript } from "@google-labs/core-kit"; -import { prompt, promptPlaceholder } from "@google-labs/template-kit"; - -const question = input({ - $id: "math-question", - title: "Math problem", - description: "Ask a math question", - examples: ["What is the square root of pi?"], -}); - -const generator = input({ - $id: "math-question", - title: "Generator", - type: annotate(object({}), { - behavior: ["board"], - }), - description: "The URL of the generator to call", - default: { kind: "board", path: "text-generator.json" }, -}); - -const instructions = - prompt`Translate the math problem below into a self-contained, -zero-argument JavaScript function named \`compute\` that can be executed -to provide the answer to the problem. - -Do not use any dependencies or libraries. - -Math Problem: ${promptPlaceholder(question, { name: "question" })} - -Solution:`.configure({ id: "math-function" }); - -const generatedCode = invoke({ - $id: "generator", - $board: generator, - text: instructions, - // TODO(aomarks) Some kind of helper that can abstract over multiple boards - // (need to convert all underyling boards to the new API first). -}).unsafeOutput("text"); - -const result = runJavascript({ - $id: "compute", - name: "compute", - code: generatedCode, - // TODO(aomarks) Implement a `code` helper that enforces params/return. -}).unsafeOutput("result"); - -export default board({ - title: "The Calculator Board", - description: - "A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.", - version: "0.0.4", - inputs: { question, generator }, - outputs: { - result: output( - // TODO(aomarks) This unsafeCast is here to match the existing schema to - // prove we can replicate it, but actually we should add a node here which - // enforces that the type is string, and errors if it doesn't match. An - // assertType node in core-kit, maybe? - unsafeCast(result, "string"), - { - id: "answer", - title: "Answer", - description: "The answer to the math problem", - } - ), - }, -}); diff --git a/packages/example-boards/src/boards/playground/nager.date/available-countries.ts b/packages/example-boards/src/boards/playground/nager.date/available-countries.ts deleted file mode 100644 index 784bffd91e4..00000000000 --- a/packages/example-boards/src/boards/playground/nager.date/available-countries.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { board, output } from "@breadboard-ai/build"; -import { fetch } from "@google-labs/core-kit"; - -const fetchResult = fetch({ - $metadata: { - $id: "fetchResult", - title: "API Fetch Results", - description: "Calling the Nager Date API to get the the available countries", - }, - url: "https://date.nager.at/api/v3/AvailableCountries", - method: "GET" -}); - -const countries = output(fetchResult.outputs.response, { - title: "Available Countries", - description: "A list of available countries", -}); - -export default board({ - title: "Nager Date Available Countries API", - description: "Get the available countries for the Nager Date API", - version: "0.1.0", - inputs: {}, - outputs: { countries }, -}); diff --git a/packages/example-boards/src/boards/playground/nager.date/country-info.ts b/packages/example-boards/src/boards/playground/nager.date/country-info.ts deleted file mode 100644 index 9376abfe381..00000000000 --- a/packages/example-boards/src/boards/playground/nager.date/country-info.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { board, enumeration, input, output } from "@breadboard-ai/build"; -import { fetch } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; -import { countryCodes } from "../../../utils/countryCodes"; - -const countryCode = input({ - title: "countryCode", - type: enumeration(...countryCodes), - description: "The data for countryCode", - default: "US" -}); - -const url = urlTemplate({ - $id: "url", - template: "https://date.nager.at/api/v3/CountryInfo/{countryCode}", - countryCode: countryCode -}); - -const fetchResult = fetch({ - $id: "fetchResult", - method: "GET", - url: url.outputs.url, -}); - -const info = output(fetchResult.outputs.response, { - title: "Country Info", - description: "The country info for the selected country code from the Nager Date API" -}); - -export default board({ - title: "Nager Date Country Info API", - description: "Get the country info for the Nager Date API", - version: "0.1.0", - inputs: { countryCode }, - outputs: { info }, -}); diff --git a/packages/example-boards/src/boards/playground/nager.date/is-today-public-holiday.ts b/packages/example-boards/src/boards/playground/nager.date/is-today-public-holiday.ts deleted file mode 100644 index a9afe59170d..00000000000 --- a/packages/example-boards/src/boards/playground/nager.date/is-today-public-holiday.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { board, enumeration, input, output } from "@breadboard-ai/build"; -import { fetch, code } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; -import { countryCodes } from "../../../utils/countryCodes"; - -const countryCode = input({ - title: "countryCode", - type: enumeration(...countryCodes), - description: "The data for countryCode", - default: "US" -}); - -const offset = input({ - title: "offset", - type: "number", - description: "utc timezone offset", - default: 0, -}); - -const validatedOffset = code( - { - $id: "validatedOffset", - offset - }, - { offset: "number" }, - ({ offset }) => { - if (offset > 12 || offset < -12) { - throw new Error(`Invalid offset input: ${offset}. Offset must be maximum 12 and minimum -12.`); - } - return { offset } - }); - -const url = urlTemplate({ - $id: "urlTemplate", - template: "https://date.nager.at/Api/v3/IsTodayPublicHoliday/{countryCode}?{&offset}", - countryCode: countryCode, - offset: validatedOffset.outputs.offset, -}); - -const fetchResult = fetch({ - $id: "fetchResult", - raw: true, - method: "GET", - url: url.outputs.url, -}); - -const statusCodeToResult = code( - { - $id: "statusCodeToResult", - status: fetchResult.outputs.status - }, - { isPublicHoliday: "boolean" }, - ({ status }: { status: number; }): { - isPublicHoliday: boolean; - } => { - if (status === 200) { - return { - isPublicHoliday: true, - }; - } else if (status === 204) { - return { - isPublicHoliday: false, - }; - } - throw new Error(`Unexpected status code: ${status}`); - } -); - -const publicHolidayResult = output(statusCodeToResult.outputs.isPublicHoliday, { - title: "Public Holiday Result", - description: "A boolean indicating if today is a bank holiday for the given country code from the Nager Date API", -}); - -export default board({ - title: "Is Today a Public Holiday", - description: "Get the public holidays for today for the Nager Date API", - version: "0.1.0", - inputs: { countryCode, offset }, - outputs: { publicHolidayResult } -}); diff --git a/packages/example-boards/src/boards/playground/nager.date/long-weekend.ts b/packages/example-boards/src/boards/playground/nager.date/long-weekend.ts deleted file mode 100644 index fd4bef3c8d0..00000000000 --- a/packages/example-boards/src/boards/playground/nager.date/long-weekend.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { board, enumeration, input, output } from "@breadboard-ai/build"; -import { fetch } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; -import { countryCodes } from "../../../utils/countryCodes"; - -const countryCode = input({ - title: "countryCode", - type: enumeration(...countryCodes), - description: "The data for countryCode", - default: "US" -}); - -const year = input({ - title: "year", - type: "number", - description: "The data for year", - default: new Date().getFullYear(), -}); - -const url = urlTemplate({ - $id: "url", - template: "https://date.nager.at/api/v3/LongWeekend/{year}/{countryCode}", - year: year, - countryCode: countryCode, -}); - -const fetchResult = fetch({ - $id: "fetchResult", - method: "GET", - url: url.outputs.url, -}); - -const info = output(fetchResult.outputs.response, { - title: "Long Weekend Info", - description: "The long weekend info for the selected country code for the given year from the Nager Date API" -}); - -export default board({ - title: "Nager Date Long Weekend API", - description: "API for long weekends", - version: "0.1.0", - inputs: { countryCode, year }, - outputs: { info } -}); diff --git a/packages/example-boards/src/boards/playground/nager.date/next-holiday-worldwide.ts b/packages/example-boards/src/boards/playground/nager.date/next-holiday-worldwide.ts deleted file mode 100644 index a1fccf441e2..00000000000 --- a/packages/example-boards/src/boards/playground/nager.date/next-holiday-worldwide.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { anyOf, array, board, object, output } from "@breadboard-ai/build"; -import { fetch, code } from "@google-labs/core-kit"; - -const fetchResult = fetch({ - $id: "fetchResult", - method: "GET", - url: "https://date.nager.at/api/v3/NextPublicHolidaysWorldwide", -}); - -const spreadNagerDateResponse = code( - { - $id: "spreadResponse", - $metadata: { - title: "Spread", - description: "Spread the properties of the Nager Date response into a new object", - }, - obj: fetchResult.outputs.response - }, - { - results: array( - object({ - date: "string", - localName: "string", - name: "string", - countryCode: "string", - fixed: "boolean", - global: "boolean", - counties: anyOf(array("string"), "null"), - launchYear: anyOf("number", "null"), - types: array("string"), - })) - }, - ({ obj }) => { - if (typeof obj !== "object") { - throw new Error(`object is of type ${typeof obj} not object`); - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return { results: { ...obj } } as any; - } -); - -const dates = output( - spreadNagerDateResponse.outputs.results, { - title: "Public Holidays Worldwide", - description: "A list of public holidays worldwide from the Nager Date API", -}); - -export default board({ - title: "Nager Date Next Public Holidays Worldwide API", - description: "Get the next public holidays worldwide for the Nager Date API", - version: "0.1.0", - inputs: {}, - outputs: { dates } -}); diff --git a/packages/example-boards/src/boards/playground/nager.date/next-public-holiday.ts b/packages/example-boards/src/boards/playground/nager.date/next-public-holiday.ts deleted file mode 100644 index 96d1214146f..00000000000 --- a/packages/example-boards/src/boards/playground/nager.date/next-public-holiday.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { board, input, output } from "@breadboard-ai/build"; -import { fetch } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; - -const countryCode = input({ - title: "Country Code", - description: "Two-letter country code", -}); - -const url = urlTemplate({ - $metadata: { - title: "URL Template", - description: "Creating the API URL", - }, - template: "https://date.nager.at/api/v3/NextPublicHolidays/{countryCode}", - countryCode: countryCode, -}); - -const callAPI = fetch({ - $metadata: { - title: "Call API", - description: - "Calling the Nager Date API to get the next public holiday for the given country", - }, - url: url.outputs.url, - method: "GET", - headers: { - "Content-Type": "application/json", - }, -}); - -const holidays = output(callAPI.outputs.response, { - title: "Holidays", - description: "A list of public holidays for the given country", -}); - -export default board({ - title: "Nager Date Next Public Holiday", - description: "Get the next public holiday for a given country", - version: "0.0.1", - inputs: { countryCode }, - outputs: { holidays }, -}); diff --git a/packages/example-boards/src/boards/playground/nager.date/public-holidays.ts b/packages/example-boards/src/boards/playground/nager.date/public-holidays.ts deleted file mode 100644 index 44696ae9bc8..00000000000 --- a/packages/example-boards/src/boards/playground/nager.date/public-holidays.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { anyOf, array, board, enumeration, input, object, output } from "@breadboard-ai/build"; -import { code, fetch } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; -import { countryCodes } from "../../../utils/countryCodes"; - -const countryCode = input({ - title: "countryCode", - type: enumeration(...countryCodes), - description: "The data for countryCode", - default: "US" -}); - -const year = input({ - title: "year", - type: "number", - description: "The data for year", - default: new Date().getFullYear(), -}); - -const url = urlTemplate({ - $id: "url", - template: "https://date.nager.at/api/v3/PublicHolidays/{year}/{countryCode}", - year: year, - countryCode: countryCode, -}); - -const fetchResult = fetch({ - $id: "fetchResult", - method: "GET", - url: url.outputs.url, -}); - -const spreadNagerDateResponse = code( - { - $id: "spreadResponse", - $metadata: { - title: "Spread", - description: "Spread the properties of the Nager Date response into a new object", - }, - obj: fetchResult.outputs.response - }, - { - results: array( - object({ - date: "string", - localName: "string", - name: "string", - countryCode: "string", - fixed: "boolean", - global: "boolean", - counties: anyOf(array("string"), "null"), - launchYear: anyOf("number", "null"), - types: array("string"), - })) - }, - ({ obj }) => { - if (typeof obj !== "object") { - throw new Error(`object is of type ${typeof obj} not object`); - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return { results: { ...obj } } as any; - } -); - -const dates = output( - spreadNagerDateResponse.outputs.results, { - title: "Public Holidays", - description: "A list of public holidays for the selected country code and for the given year from the Nager Date API", -}); - -export default board({ - title: "Nager Date Public Holidays API", - description: "Get the public holidays for the Nager Date API", - version: "0.1.0", - inputs: { countryCode, year }, - outputs: { dates } -}); diff --git a/packages/example-boards/src/boards/playground/object-manipulator.json b/packages/example-boards/src/boards/playground/object-manipulator.json deleted file mode 100644 index 56cb73c78b7..00000000000 --- a/packages/example-boards/src/boards/playground/object-manipulator.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "title": "Object Manipulator", - "description": "Manipulate an object by picking or omitting keys", - "edges": [ - { - "from": "fn-35", - "to": "output-36", - "out": "object", - "in": "object" - }, - { - "from": "input-34", - "to": "fn-35", - "out": "keys", - "in": "keys" - }, - { - "from": "input-34", - "to": "fn-35", - "out": "mode", - "in": "mode" - }, - { - "from": "input-34", - "to": "fn-35", - "out": "object", - "in": "object" - }, - { - "from": "input-34", - "to": "fn-35", - "out": "strict", - "in": "strict" - } - ], - "nodes": [ - { - "id": "input-34", - "type": "input", - "configuration": { - "examples": [ - { - "object": { - "forename": "John", - "surname": "Smith", - "age": 30, - "city": "New York", - "dateOfBirth": "1990-01-01T00:00:00.000Z" - }, - "keys": [ - "forename", - "surname" - ], - "mode": "pick", - "strict": false - }, - { - "object": { - "forename": "John", - "surname": "Smith", - "age": 30, - "city": "New York", - "dateOfBirth": "1990-01-01T00:00:00.000Z" - }, - "keys": [ - "forename", - "surname" - ], - "mode": "omit", - "strict": false - }, - { - "object": { - "name": "John Smith", - "age": 30, - "location": "New York", - "dob": "1990-01-01T00:00:00.000Z" - }, - "keys": [ - "forename", - "surname" - ], - "mode": "pick", - "strict": true - } - ], - "schema": { - "type": "object", - "properties": { - "keys": { - "type": "array", - "examples": [ - "[\"forename\",\"surname\"]" - ], - "items": { - "type": "string" - } - }, - "mode": { - "type": "string", - "default": "pick", - "enum": [ - "pick", - "omit" - ] - }, - "object": { - "type": "object", - "examples": [ - "{\"forename\":\"John\",\"surname\":\"Smith\",\"age\":30,\"city\":\"New York\",\"dateOfBirth\":\"1990-01-01T00:00:00.000Z\"}" - ] - }, - "strict": { - "type": "boolean", - "description": "If true and a key is not found, an error will be thrown", - "default": "false" - } - } - } - }, - "metadata": { - "title": "Input" - } - }, - { - "id": "output-36", - "type": "output", - "configuration": { - "schema": { - "type": "object" - } - }, - "metadata": { - "title": "Output" - } - }, - { - "id": "fn-35", - "type": "runJavascript", - "configuration": { - "code": "const fn_35 = ({object,keys,mode=\"pick\",strict=false})=>{if(mode===\"pick\"){const result={};keys.forEach(key=>{if(strict&&!object[key]){throw new Error(`Key \"${key}\" not found in object`)}result[key]=object[key]});return{object:result}}else{const result={...object};keys.forEach(key=>{if(strict&&!object[key]){throw new Error(`Key \"${key}\" not found in object`)}delete result[key]});return{object:result}}};", - "name": "fn_35", - "raw": true - }, - "metadata": { - "title": "Manipulation" - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/open-alex-entity-search-list.ts b/packages/example-boards/src/boards/playground/open-alex-entity-search-list.ts deleted file mode 100644 index 140e5687b1f..00000000000 --- a/packages/example-boards/src/boards/playground/open-alex-entity-search-list.ts +++ /dev/null @@ -1,137 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - anyOf, - array, - board, - enumeration, - input, - object, - output, -} from "@breadboard-ai/build"; -import { fetch, code } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; - -const entity = input({ - description: "Entity type to search for", - type: enumeration( - "works", - "authors", - "sources", - "institutions", - "topics", - "publishers", - "funders", - "concepts" - ), - default: "works", - title: "Entity", -}); - -const page = input({ - type: "number", - default: 5, - title: "Results per page", - description: "Number of results to return per page", -}); - -const per_page = input({ - type: "number", - default: 5, - title: "Results per page", - description: "Number of results to return per page", -}); - -const search = input({ - type: "string", - title: "Search term", - default: "Artificial Intelligence", - description: "Search term to search for, double quotes for exact match", -}); - -const select = input({ - type: "string", - title: "Select", - default: "id,display_name,title,relevance_score", - description: "Comma-separated list of fields to return", -}); - -const url = urlTemplate({ - $id: "urlTemplate", - template: - "https://api.openalex.org/{entity}?search={search}&page={page}&per_page={per_page}&select={select}", - entity: entity, - page: page, - per_page: per_page, - search: search, - select: select, -}); - -const fetchResult = fetch({ - $id: "fetch", - method: "GET", - url: url.outputs.url, -}); - -const spreadOpenAlexResponse = code( - { - $id: "spreadResponse", - $metadata: { - title: "Spread", - description: "Spread the properties of the Open Alex response", - }, - obj: fetchResult.outputs.response - }, - { - results: array(object({ - id: "string", - display_name: "string", - title: "string", - relevance_score: "number" - }, anyOf("string", "number", "boolean", "unknown"))), - meta: object({ - count: "number", - db_response_time_ms: "number", - page: "number", - per_page: "number" - }) - }, - ({ obj }) => { - if (typeof obj !== "object") { - throw new Error(`object is of type ${typeof obj} not object`); - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return { ...obj } as any; - } -); - -export default board({ - title: "Open Alex Entity Search Results", - description: "Query the OpenAlex API for a list entities", - version: "0.1.0", - inputs: { - entity, - page, - per_page, - search, - select, - }, - outputs: { - url: output(url.outputs.url, { - title: "URL", - description: "The fetched Open Alex URL", - }), - meta: output(spreadOpenAlexResponse.outputs.meta, { - title: "Search Result Metadata", - description: "The metadata from the search results", - }), - results: output(spreadOpenAlexResponse.outputs.results, { - title: "Entity Search Results", - description: "A list of entities from the search results", - }), - } -}); diff --git a/packages/example-boards/src/boards/playground/openai-gpt-35-turbo.ts b/packages/example-boards/src/boards/playground/openai-gpt-35-turbo.ts deleted file mode 100644 index 77c36fc07e0..00000000000 --- a/packages/example-boards/src/boards/playground/openai-gpt-35-turbo.ts +++ /dev/null @@ -1,217 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { annotate, anyOf, array, board, enumeration, input, object, output, unsafeType } from "@breadboard-ai/build"; -import { Schema } from "@google-labs/breadboard"; -import { secret, fetch } from "@google-labs/core-kit"; -import { jsonata } from "@google-labs/json-kit"; - -const textPartType = object({ text: "string" }); - -const imagePartType = object({ - inlineData: object({ - mimeType: enumeration( - "image/png", - "image/jpeg", - "image/heic", - "image/heif", - "image/webp" - ), - data: "string", - }), -}); - -const functionCallPartType = object({ - function_call: object({ - name: "string", - args: object({}, "string"), - }), -}); - -const functionResponsePartType = object({ - function_response: object({ - name: "string", - response: "unknown", - }), -}); - -const partType = anyOf( - textPartType, - imagePartType, - functionCallPartType, - functionResponsePartType -); - -const generateContentContentsType = object({ - role: enumeration("model", "user", "tool", "$metadata"), - parts: array(partType), -}); - -const functionDeclaration = object({ - name: "string", - description: "string", - parameters: unsafeType({ type: "object" }), -}); - -const textDefault = "What is the correct term for the paddle in cricket?" - -const text = input({ - $id: "Text", - type: "string", - title: "Text", - description: "The text to generate", - default: textDefault, - examples: ["What is the correct term for the paddle in cricket?"], -}); - -const toolsExample = [ - { - name: "The_Calculator_Board", - description: - "A simple AI pattern that leans on the power of the LLMs to generate language to solve math problems.", - parameters: { - type: "object", - properties: { - text: { - type: "string", - description: "Ask a math question", - }, - }, - required: ["text"], - }, - }, - { - name: "The_Search_Summarizer_Board", - description: - "A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.", - parameters: { - type: "object", - properties: { - text: { - type: "string", - description: "What would you like to search for?", - }, - }, - required: ["text"], - }, - }, -]; - -const tools = input({ - $id: "Tools", - type: array(functionDeclaration), - title: "Tools", - description: "An array of functions to use for tool-calling", - default: [], - examples: [toolsExample], -}); - -const contextDefault = [ - { - role: "user", - parts: [{ text: "You are a pirate. Please talk like a pirate." }], - }, - { - role: "model", - parts: [{ text: "Arr, matey!" }], - }, -]; - -const context = input({ - $id: "Context", - type: array( - annotate(generateContentContentsType, { - behavior: ["llm-content"], - }) - ), - title: "Context", - description: "An array of messages to use as conversation context", - default: [], - // eslint-disable-next-line @typescript-eslint/no-explicit-any - examples: [contextDefault as any], -}); - -const formattedRequest = jsonata({ - $id: "formatParameters", - expression: `( - $context := $append( - context ? context, [ - { - "role": "user", - "parts": [{ "text": text }] - } - ]); - OPENAI_API_KEY ? text ? { - "headers": { - "Content-Type": "application/json", - "Authorization": "Bearer " & OPENAI_API_KEY - }, - "body": { - "model": "gpt-3.5-turbo-1106", - "messages": [$context.{ - "role": $.role = "model" ? "system" : $.role, - "content": $.parts.text - }], - "stream": useStreaming, - "temperature": 1, - "top_p": 1, - "tools": tools ? [tools.{ "type": "function", "function": $ }], - "frequency_penalty": 0, - "presence_penalty": 0 - }, - "stream": useStreaming, - "context": $context - } : { - "$error": "\`text\` input is required" - } : { - "$error": "\`OPENAI_API_KEY\` input is required" - } - )`, - text, - tools, - context, - useStreaming: false, - raw: true, - OPENAI_API_KEY: secret("OPENAI_API_KEY"), -}); - -const fetchResult = fetch({ - $id: "callOpenAI", - url: "https://api.openai.com/v1/chat/completions", - method: "POST", - stream: false, - headers: formattedRequest.unsafeOutput("headers"), - body: formattedRequest.unsafeOutput("body") -}); - -const jsonResponse = jsonata({ - $id: "getResponse", - expression: `choices[0].message.{ - "text": $boolean(content) ? content, - "tool_calls": tool_calls.function ~> | $ | { "args": $eval(arguments) }, "arguments" | - }`, - raw: true, - json: fetchResult.outputs.response, -}); - -const getNewContext = jsonata({ - $id: "getNewContext", - expression: `$append(messages, response.choices[0].message)`, - messages: formattedRequest.unsafeOutput("context"), -}); - -export default board({ - title: "OpenAI GPT-3.5-turbo", - description: - "This board is the simplest possible invocation of OpenAI's GPT-3.5 API to generate text.", - version: "0.1.0", - inputs: { text, tools, context }, - outputs: { - context: output(getNewContext.unsafeOutput("result")), - text: output(jsonResponse.unsafeOutput("text")), - toolCalls: output(jsonResponse.unsafeOutput("tool_calls")) - }, -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/openai-gpt-4-turbo-vision.ts b/packages/example-boards/src/boards/playground/openai-gpt-4-turbo-vision.ts deleted file mode 100644 index d2c85635d12..00000000000 --- a/packages/example-boards/src/boards/playground/openai-gpt-4-turbo-vision.ts +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { annotate, anyOf, array, board, enumeration, input, object, output } from "@breadboard-ai/build"; -import { secret, fetch } from "@google-labs/core-kit"; -import { jsonata } from "@google-labs/json-kit"; - -const textPartType = object({ text: "string" }); - -const imagePartType = object({ - inlineData: object({ - mimeType: enumeration( - "image/png", - "image/jpeg", - "image/heic", - "image/heif", - "image/webp" - ), - data: "string", - }), -}); - -const partType = anyOf( - textPartType, - imagePartType -); - -const generateContentContentsType = object({ - role: "string", - parts: array(partType), -}); - -const content = input({ - $id: "Content", - type: array( - annotate(generateContentContentsType, { - behavior: ["llm-content"], - }) - ), - title: "Context", - description: "An array of messages to use as conversation context", -}); - -const fetchResult = fetch({ - $id: "openai", - url: "https://api.openai.com/v1/chat/completions", - method: "POST", - stream: false, - headers: jsonata({ - $id: "makeHeaders", - expression: `{ - "Content-Type": "application/json", - "Authorization": "Bearer " & $.OPENAI_API_KEY - }`, - OPENAI_API_KEY: secret("OPENAI_API_KEY"), - }).unsafeOutput("result"), - body: jsonata({ - $id: "makeBody", - expression: `{ - "model": "gpt-4-turbo", - "messages": [ - { - "role": "user", - "content": $.content.parts.({ - "type": $exists($.text) ? "text" : "image_url", - "text": $exists($.text) ? $.text : undefined, - "image_url": $exists($.inlineData) ? { - "url": "data:" & $.inlineData.mimeType & ";base64," & $.inlineData.data - } : undefined - }) - } - ], - "stream": $.useStreaming, - "temperature": 1, - "max_tokens": 256, - "top_p": 1, - "frequency_penalty": 0, - "presence_penalty": 0 - }`, - content, - useStreaming: false - }).unsafeOutput("result") -}); - -const formattedResponse = jsonata({ - $id: "getResponse", - expression: `choices[0].message.content`, - json: fetchResult.outputs.response, -}); - -export default board({ - title: "OpenAI GPT-4 Turbo Vision", - description: - "This board is the simplest possible invocation of OpenAI's GPT 4 Turbo API, using its vision capabilities to generate text from multipart inputs.", - version: "0.1.0", - inputs: { content }, - outputs: { - text: output(formattedResponse.unsafeOutput("result")), - } -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/search-summarize.ts b/packages/example-boards/src/boards/playground/search-summarize.ts deleted file mode 100644 index 6ea05f7d304..00000000000 --- a/packages/example-boards/src/boards/playground/search-summarize.ts +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { annotate, board, input, object, output } from "@breadboard-ai/build"; -import { fetch, invoke, secret } from "@google-labs/core-kit"; -import { promptTemplate, urlTemplate } from "@google-labs/template-kit"; -import { jsonata } from "@google-labs/json-kit"; - -const query = input({ - type: "string", - title: "Query", - description: "What would you like to search for?", -}); - -const generator = input({ - $id: "text-generator", - title: "Generator", - type: annotate(object({}), { - behavior: ["board"], - }), - description: "The URL of the generator to call", - default: { kind: "board", path: "text-generator.json" } -}); - -const apiKey = secret("API_KEY"); -const cseId = secret("GOOGLE_CSE_ID"); - -const url = urlTemplate({ - $id: "customSearchURL", - $metadata: { - title: "CSE URL Template", - }, - template: - "https://www.googleapis.com/customsearch/v1?key={API_KEY}&cx={GOOGLE_CSE_ID}&q={query}", - query, - API_KEY: apiKey, - GOOGLE_CSE_ID: cseId -}); - -const fetchResult = fetch({ - $id: "search", - url -}); - -const snippets = jsonata({ - $id: "getSnippets", - expression: "$join(items.snippet, '\n')", - json: fetchResult.outputs.response -}).unsafeOutput("result"); - -const prompt = promptTemplate({ - $id: "summarizing-template", - template: "Use context below to answer this question:\n\n##Question:\n{{question}}\n\n## Context {{context}}\n\\n## Answer:\n", - question: query, - context: snippets -}); - -const llmResponse = invoke({ - $id: "llm-response", - $board: generator, - text: prompt -}).unsafeOutput("text"); - -export default board({ - title: "The Search Summarizer Board", - description: "A simple AI pattern that first uses Google Search to find relevant bits of information and then summarizes them using LLM.", - version: "0.2.0", - inputs: { query, generator }, - outputs: { result: output(llmResponse) }, -}); diff --git a/packages/example-boards/src/boards/playground/simplest.ts b/packages/example-boards/src/boards/playground/simplest.ts deleted file mode 100644 index 0e5273cc455..00000000000 --- a/packages/example-boards/src/boards/playground/simplest.ts +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - board, - enumeration, - input, - output, -} from "@breadboard-ai/build"; -import { geminiText } from "@google-labs/gemini-kit"; - -const prompt = input({ - type: "string", - title: "Prompt", - description: "The prompt to generate a completion for", - examples: ["Tell me a fun story about playing with breadboards"], -}); - -const model = input({ - type: enumeration("gemini-1.5-flash-latest", "gemini-1.5-pro-latest") -}); - -const llmResponse = geminiText({ model, text: prompt }); - -export default board({ - title: "The simplest LLM-based board", - description: - "This board is as simple as it gets: takes text as input and invokes Gemini to generate a text response as output.", - version: "0.1.0", - inputs: { model, prompt }, - outputs: { - response: output(llmResponse.outputs.text, { - title: "Response", - description: "The completion generated by the LLM", - }), - } -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/summarize-single-iteration.json b/packages/example-boards/src/boards/playground/summarize-single-iteration.json deleted file mode 100644 index 84bd596251f..00000000000 --- a/packages/example-boards/src/boards/playground/summarize-single-iteration.json +++ /dev/null @@ -1,507 +0,0 @@ -{ - "title": "Dense text summarizer (single iteration)", - "description": "A simple workflow of two structured workers: one comes up with a summary, the other reviews it and suggests improvements.", - "version": "0.0.1", - "edges": [ - { - "from": "critic", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "critic", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "input-1", - "to": "summarizer", - "out": "context", - "in": "context" - }, - { - "from": "summarizer", - "to": "critic", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "Text to summarize", - "default": "[]", - "examples": [ - "In one aspect, a system is described to include computer data servers each storing and operable to serve a partition of a collection of data. The respective partitions together constitute the collection of data and each respective partition is less than the collection of data. This system also includes a processing server operable to obtain data from the data servers and to use the obtained data to process an input and to produce an output. The system can be implemented to include one or more replica data servers for each of the data servers. In one implementation, the collection of data is data for a language model for a target language. The language model includes n grams in the target language and statistical data for each of the n grams. The n grams can include N-grams with N greater than 3. The processing server is a translation server operable to translate a text in a source language in the input into the target language using the obtained data from the language model. The processing server can be implemented in various configurations, e.g., a speech recognition server operable to convert a human speech in the target language in the input into a text in the target language using the obtained data from the language model, a spelling correction server operable to correct a spelling of a word in the target language in the input using the obtained data from the language model, or an optical character recognition server operable to recognize text in a received document image in the input using the obtained data from the language model." - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "format": "multiline" - } - }, - "required": [ - "context" - ] - } - } - }, - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "context", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - }, - "json": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "JSON", - "description": "The validated JSON." - } - } - } - } - }, - { - "id": "critic", - "type": "structuredWorker", - "configuration": { - "instruction": "You are a reviewer of summaries produced from patent applications, helping to make the summaries become more accessible and clear. Compare the latest summary with the original text and identify three areas of improvement. What is missing? What could be better phrased? What could be removed? Is there any technical jargon that could be replaced with simpler terms?", - "schema": { - "type": "object", - "properties": { - "improvements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "improvement": { - "type": "string", - "description": "a suggested improvement" - }, - "reasoning": { - "type": "string", - "description": "reasoning behind the improvement" - } - } - } - } - } - } - } - }, - { - "id": "summarizer", - "type": "structuredWorker", - "configuration": { - "instruction": "You are a genius legal expert. You specialize in carefully reading the dense paragraphs of patent application texts and summarizing them in a few simple sentences that most people can understand. Incorporate all improvements, if they are suggested", - "schema": { - "type": "object", - "properties": { - "summary": { - "type": "string", - "description": "the summary" - } - } - } - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/summarizer.json b/packages/example-boards/src/boards/playground/summarizer.json deleted file mode 100644 index 646440e5dfc..00000000000 --- a/packages/example-boards/src/boards/playground/summarizer.json +++ /dev/null @@ -1,817 +0,0 @@ -{ - "title": "Dense text summarizer", - "description": "Turns particularly dense text passages into easy-to-understand summaries", - "version": "0.0.1", - "edges": [ - { - "from": "extractSummary", - "to": "output-2", - "out": "summary", - "in": "summary" - }, - { - "from": "finalSummarizer", - "to": "extractSummary", - "out": "json", - "in": "json" - }, - { - "from": "input-1", - "to": "iterate", - "out": "n", - "in": "max" - }, - { - "from": "input-1", - "to": "iterate", - "out": "paragraph", - "in": "context" - }, - { - "from": "iterate", - "to": "finalSummarizer", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "n": { - "type": "number", - "title": "How many times should workers iterate?", - "description": "The maximum number of repetitions to make (set to -1 to go infinitely)", - "default": "-1", - "examples": [ - "3" - ] - }, - "paragraph": { - "type": "string", - "title": "Text to summarize", - "description": "Initial conversation context", - "default": "[]", - "examples": [ - "In one aspect, a system is described to include computer data servers each storing and operable to serve a partition of a collection of data. The respective partitions together constitute the collection of data and each respective partition is less than the collection of data. This system also includes a processing server operable to obtain data from the data servers and to use the obtained data to process an input and to produce an output. The system can be implemented to include one or more replica data servers for each of the data servers. In one implementation, the collection of data is data for a language model for a target language. The language model includes n grams in the target language and statistical data for each of the n grams. The n grams can include N-grams with N greater than 3. The processing server is a translation server operable to translate a text in a source language in the input into the target language using the obtained data from the language model. The processing server can be implemented in various configurations, e.g., a speech recognition server operable to convert a human speech in the target language in the input into a text in the target language using the obtained data from the language model, a spelling correction server operable to correct a spelling of a word in the target language in the input using the obtained data from the language model, or an optical character recognition server operable to recognize text in a received document image in the input using the obtained data from the language model." - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "format": "multiline" - } - }, - "required": [ - "n", - "paragraph" - ] - } - } - }, - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "summary": { - "type": "string", - "title": "summary" - } - } - } - } - }, - { - "id": "extractSummary", - "type": "runJavascript", - "configuration": { - "code": "const extractSummary = ({json})=>{return{summary:json.summary}};", - "name": "extractSummary", - "raw": true - } - }, - { - "id": "finalSummarizer", - "type": "structuredWorker", - "configuration": { - "instruction": "You are a genius legal expert. You specialize in carefully reading the dense paragraphs of patent application texts and summarizing them in a few simple sentences that most people can understand. Incorporate all improvements, if they are suggested", - "schema": { - "type": "object", - "properties": { - "summary": { - "type": "string", - "description": "the summary" - } - } - } - } - }, - { - "id": "iterate", - "type": "repeater", - "configuration": { - "worker": { - "title": "Dense text summarizer (single iteration)", - "description": "A simple workflow of two structured workers: one comes up with a summary, the other reviews it and suggests improvements.", - "version": "0.0.1", - "edges": [ - { - "from": "critic", - "to": "output-2", - "out": "context", - "in": "context" - }, - { - "from": "critic", - "to": "output-2", - "out": "json", - "in": "json" - }, - { - "from": "summarizer", - "to": "critic", - "out": "context", - "in": "context" - }, - { - "from": "input-1", - "to": "summarizer", - "out": "context", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "title": "context" - }, - "json": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "JSON", - "description": "The validated JSON." - } - } - } - } - }, - { - "id": "critic", - "type": "structuredWorker", - "configuration": { - "instruction": "You are a reviewer of summaries produced from patent applications, helping to make the summaries become more accessible and clear. Compare the latest summary with the original text and identify three areas of improvement. What is missing? What could be better phrased? What could be removed? Is there any technical jargon that could be replaced with simpler terms?", - "schema": { - "type": "object", - "properties": { - "improvements": { - "type": "array", - "items": { - "type": "object", - "properties": { - "improvement": { - "type": "string", - "description": "a suggested improvement" - }, - "reasoning": { - "type": "string", - "description": "reasoning behind the improvement" - } - } - } - } - } - } - } - }, - { - "id": "summarizer", - "type": "structuredWorker", - "configuration": { - "instruction": "You are a genius legal expert. You specialize in carefully reading the dense paragraphs of patent application texts and summarizing them in a few simple sentences that most people can understand. Incorporate all improvements, if they are suggested", - "schema": { - "type": "object", - "properties": { - "summary": { - "type": "string", - "description": "the summary" - } - } - } - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "string", - "title": "Text to summarize", - "default": "[]", - "examples": [ - "In one aspect, a system is described to include computer data servers each storing and operable to serve a partition of a collection of data. The respective partitions together constitute the collection of data and each respective partition is less than the collection of data. This system also includes a processing server operable to obtain data from the data servers and to use the obtained data to process an input and to produce an output. The system can be implemented to include one or more replica data servers for each of the data servers. In one implementation, the collection of data is data for a language model for a target language. The language model includes n grams in the target language and statistical data for each of the n grams. The n grams can include N-grams with N greater than 3. The processing server is a translation server operable to translate a text in a source language in the input into the target language using the obtained data from the language model. The processing server can be implemented in various configurations, e.g., a speech recognition server operable to convert a human speech in the target language in the input into a text in the target language using the obtained data from the language model, a spelling correction server operable to correct a spelling of a word in the target language in the input using the obtained data from the language model, or an optical character recognition server operable to recognize text in a received document image in the input using the obtained data from the language model." - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "format": "multiline" - } - }, - "required": [ - "context" - ] - } - } - } - ], - "graphs": {} - } - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/super-worker-test.json b/packages/example-boards/src/boards/playground/super-worker-test.json deleted file mode 100644 index f4f6e791f32..00000000000 --- a/packages/example-boards/src/boards/playground/super-worker-test.json +++ /dev/null @@ -1,522 +0,0 @@ -{ - "title": "Specialist Testing Grounds", - "description": "A board for testing the Specialist worker", - "version": "0.0.1", - "edges": [ - { - "from": "input-1", - "to": "specialist-3", - "out": "context", - "in": "in" - }, - { - "from": "specialist-3", - "to": "specialist-4", - "out": "out", - "in": "in" - }, - { - "from": "specialist-4", - "to": "specialist-5", - "out": "out", - "in": "in" - }, - { - "from": "specialist-5", - "to": "output-2", - "out": "out", - "in": "context" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "object", - "behavior": [ - "llm-content" - ], - "title": "Book Specs", - "description": "Incoming conversation context", - "examples": [ - "{\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"book description: This book will be about breadboards and how awesome they are:\\n\\nchapter target: 10\\n\\npage target: 400\\n\\nfiction genre: space opera\\n\\nsetting: the planet where there are no breadboards\\n\\nstory arc: A girl named Aurora invents a breadboard on the planet where breadboards are strictly forbidden. Through struggles and determination, and with the help of trusted friends, Aurora overcomes many challenges and changes the whole planet for the better.\\n\\ntonality: futuristic struggle, but optimistic\\n\\nworking title: Aurora\\n\"\n }\n ]\n}" - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - }, - "required": [ - "context" - ] - } - } - }, - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context out", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - } - } - } - }, - { - "id": "specialist-3", - "type": "specialist", - "configuration": { - "persona": { - "parts": [ - { - "text": "You are a famous author. You are writing a novel.\n\nYour well-established process starts with collecting the book description, chapter target, page target, fiction genre, setting, story arc, tonality and the working title.\n\nThen, your first step is to write a detailed outline for the novel. You keep the page target in mind for the finished novel, so your outline typically contains contain key bullets for the story arc across the chapters. You usually create a part of the outline for each chapter. You also keep in mind that the outline must cover at least the target number of chapters.\n\nYou are very creative and you pride yourself in adding interesting twists and unexpected turns of the story, something that keeps the reader glued to your book." - } - ] - }, - "task": { - "parts": [ - { - "text": "Write an outline for a novel, following the provided specs." - } - ] - } - }, - "metadata": { - "title": "Outline Writer" - } - }, - { - "id": "specialist-4", - "type": "specialist", - "configuration": { - "persona": { - "parts": [ - { - "text": "You are an accomplished book editor and publisher. Your specialty is being able to recognize what story elements and characters will make a great novel. You are great at giving insightful feedback to authors to help them make their novels better." - } - ] - }, - "task": { - "parts": [ - { - "text": "Your friend, an accomplished author, has written an outline for a new book and has asked you for insightful feedback.\n\nReview the outline that the author submitted. Please read it very carefully. Then, provide feedback for the author. Give the author up to five specific suggestions to make the novel more compelling and have more chance to be a bestseller!" - } - ] - } - }, - "metadata": { - "title": "Outline Critic" - } - }, - { - "id": "specialist-5", - "type": "specialist", - "configuration": { - "persona": { - "parts": [ - { - "text": "You are a famous author. You are writing a novel.\n\nYou have written a first draft of your outline, and then asked an outstanding book editor and publisher to give you suggestions. Based on their suggestions you are going to rewrite and improve your outline.\n\nThis is great feedback and you want to try to incorporate some of it, while still staying true to your original vision for the novel." - } - ] - }, - "task": { - "parts": [ - { - "text": "Please write an improved outline for your novel, by taking the feedback into account." - } - ] - } - }, - "metadata": { - "title": "Outline Editor" - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/team-builder.json b/packages/example-boards/src/boards/playground/team-builder.json deleted file mode 100644 index 89337930074..00000000000 --- a/packages/example-boards/src/boards/playground/team-builder.json +++ /dev/null @@ -1,638 +0,0 @@ -{ - "title": "Team Builder", - "description": "Build a team of experts", - "version": "0.0.1", - "edges": [ - { - "from": "createPrompts", - "to": "output-2", - "out": "list", - "in": "prompts" - }, - { - "from": "input-1", - "to": "jobDescriptions", - "out": "purpose", - "in": "context" - }, - { - "from": "jobDescriptions", - "to": "splitJobDescriptions", - "out": "json", - "in": "json" - }, - { - "from": "jobDescriptions", - "to": "workflow", - "out": "context", - "in": "context" - }, - { - "from": "splitJobDescriptions", - "to": "createPrompts", - "out": "result", - "in": "list" - }, - { - "from": "workflow", - "to": "output-2", - "out": "json", - "in": "json" - } - ], - "nodes": [ - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "purpose": { - "type": "array", - "title": "Purpose", - "default": "[]", - "examples": [ - "Create high quality rhyming poems that will be used as lyrics for jingles in TV commercials. Creating melodies and producing music is not part of job." - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - }, - "format": "multiline" - } - }, - "required": [ - "purpose" - ] - } - } - }, - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "json": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "JSON", - "description": "The validated JSON." - }, - "prompts": { - "type": "array", - "title": "List", - "description": "The list of outputs from the board.", - "items": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": true - } - } - } - } - } - }, - { - "id": "createPrompts", - "type": "map", - "configuration": { - "board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "generatePrompt", - "to": "output-2", - "out": "json", - "in": "item" - }, - { - "from": "input-1", - "to": "generatePrompt", - "out": "item", - "in": "context" - } - ], - "nodes": [ - { - "id": "output-2", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "JSON", - "description": "The validated JSON." - } - } - } - } - }, - { - "id": "generatePrompt", - "type": "structuredWorker", - "configuration": { - "instruction": "You are an expert in creating perfect system prompts for LLM agents from job descriptions. Create a prompt for the the following job description", - "schema": { - "type": "object", - "properties": { - "prompt": { - "type": "string", - "description": "the prompt for the job description" - } - } - } - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": "array", - "title": "Context", - "default": "[]", - "examples": [ - "[\n {\n \"role\": \"user\",\n \"parts\": [\n {\n \"text\": \"the universe within us\"\n }\n ]\n }\n]" - ], - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "user", - "model", - "tool" - ] - }, - "parts": { - "type": "array", - "items": { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - }, - { - "type": "object", - "anyOf": [ - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "looper" - ] - }, - "data": { - "type": "object", - "properties": { - "max": { - "type": "number" - }, - "todo": { - "type": "array", - "items": { - "type": "object", - "properties": { - "task": { - "type": "string" - } - }, - "required": [ - "task" - ], - "additionalProperties": false - } - }, - "doneMarker": { - "type": "string" - }, - "done": { - "type": "boolean" - }, - "appendLast": { - "type": "boolean" - }, - "returnLast": { - "type": "boolean" - }, - "next": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "$metadata" - ] - }, - "type": { - "type": "string", - "enum": [ - "split" - ] - }, - "data": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "start", - "next", - "end" - ] - }, - "id": { - "type": "string" - } - }, - "required": [ - "type", - "id" - ], - "additionalProperties": false - } - }, - "required": [ - "role", - "type", - "data" - ], - "additionalProperties": false - } - ] - } - ], - "behavior": [ - "llm-content" - ] - } - } - }, - "required": [ - "item" - ] - } - } - } - ], - "graphs": {} - } - } - } - }, - { - "id": "jobDescriptions", - "type": "structuredWorker", - "configuration": { - "instruction": "You are building a team of expert LLM-based agents a specific purpose.\n\nThese expert agents can only read text and produce text. The experts will work as a team, collaborating, creating, reviewing, critiquing, and iteratively improving the quality of the poems.\n\nPlease identify the necessary job descriptions of these experts.", - "schema": { - "type": "object", - "properties": { - "descriptions": { - "type": "array", - "items": { - "type": "object", - "properties": { - "title": { - "type": "string", - "description": "expert's title" - }, - "responsibilities": { - "type": "array", - "items": { - "type": "string", - "description": "expert's responsibilities" - } - } - } - } - } - } - } - } - }, - { - "id": "splitJobDescriptions", - "type": "jsonata", - "configuration": { - "expression": "descriptions" - } - }, - { - "id": "workflow", - "type": "structuredWorker", - "configuration": { - "instruction": "Now, describe how these agents interact in the form of a workflow. The workflow is defined as a list of pairs of agents. Each pair represents the flow of work from one agent to another.", - "schema": { - "type": "object", - "properties": { - "workflow": { - "type": "array", - "items": { - "type": "object", - "properties": { - "from": { - "type": "string", - "description": "an expert from whom the work is passed" - }, - "to": { - "type": "string", - "description": "an expert to whom the work is passed" - } - } - } - } - } - } - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/text-generator.ts b/packages/example-boards/src/boards/playground/text-generator.ts deleted file mode 100644 index 494d93e31fb..00000000000 --- a/packages/example-boards/src/boards/playground/text-generator.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { - anyOf, - board, - enumeration, - input, - object, - output, - serialize, -} from "@breadboard-ai/build"; -import { code, invoke } from "@google-labs/core-kit"; -import { geminiText } from "@google-labs/gemini-kit"; - -const text = input({ - type: "string", - title: "Text", - description: "The text to generate", -}); - -const model = input({ - type: enumeration("Gemini Pro", "GPT 3.5 Turbo") -}); - -const geminiGenerator = serialize(geminiText); - -const switchModel = code( - { model, serialized: JSON.stringify(geminiGenerator) }, - { board: anyOf(object({ kind: "string", board: "string"}), object({ kind: "string", path: "string"})), model: "string" }, - ({ model, serialized }) => { - if (model == "Gemini Pro") { - return { board: { kind: "board", board: JSON.parse(serialized) }, model: "gemini-1.5-pro-latest" } - } else { - return { board: { kind: "board", path: "openai-gpt-35-turbo.json" }, model: "N/A" } // The OpenAI board only supports one model - } - } -); - -const llmResponse = invoke({ - $id: "llm-response", - $board: switchModel.outputs.board, - text, - model: switchModel.outputs.model, -}).unsafeOutput("text"); - -const textOutput = output(llmResponse, { - title: "Text", - description: "The generated text", -}); - -export default board({ - title: "Text Generator", - description: - "This is a text generator. It can generate text using various LLMs. Currently, it supports the following models: Google Gemini Pro and OpenAI GPT-3.5 Turbo.", - version: "0.1.0", - inputs: { text, model }, - outputs: { textOutput } -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/tour-guide-writer.json b/packages/example-boards/src/boards/playground/tour-guide-writer.json deleted file mode 100644 index 996989683d7..00000000000 --- a/packages/example-boards/src/boards/playground/tour-guide-writer.json +++ /dev/null @@ -1,321 +0,0 @@ -{ - "title": "Tour Guide Writer", - "description": "This boards attempts to write a tour guide for a specified location. This time, it takes a text generator board as an input.\n\nInterestingly, because we currently don't have a way to close over the inputs of the invoked text generator, this board exposes the text generator's inputs as its own inputs.", - "version": "0.0.3", - "edges": [ - { - "from": "createGuides", - "to": "fn-6", - "out": "list", - "in": "guides" - }, - { - "from": "curry-4", - "to": "createGuides", - "out": "board", - "in": "board" - }, - { - "from": "fn-3", - "to": "createGuides", - "out": "list", - "in": "list" - }, - { - "from": "fn-3", - "to": "fn-6", - "out": "list", - "in": "activities" - }, - { - "from": "fn-6", - "to": "guide", - "out": "guide", - "in": "guide" - }, - { - "from": "parameters", - "to": "curry-4", - "out": "generator", - "in": "generator" - }, - { - "from": "parameters", - "to": "curry-4", - "out": "location", - "in": "location" - }, - { - "from": "parameters", - "to": "fn-6", - "out": "location", - "in": "location" - }, - { - "from": "parameters", - "to": "travelItinerary", - "out": "location", - "in": "location" - }, - { - "from": "parameters", - "to": "travelItineraryGenerator", - "out": "generator", - "in": "$board" - }, - { - "from": "travelItinerary", - "to": "travelItineraryGenerator", - "out": "prompt", - "in": "text" - }, - { - "from": "travelItineraryGenerator", - "to": "fn-3", - "out": "text", - "in": "itinerary" - }, - { - "from": "travelItineraryGenerator", - "to": "guide", - "out": "text", - "in": "itinerary" - } - ], - "nodes": [ - { - "id": "parameters", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "generator": { - "type": "board", - "title": "Text Generator", - "description": "The text generator to use for writing the tour guide", - "examples": [ - "text-generator.json" - ] - }, - "location": { - "type": "string", - "title": "Location", - "description": "The location for which to write a tour guide", - "examples": [ - "Stresa, Italy" - ] - } - }, - "required": [ - "location" - ] - } - } - }, - { - "id": "guide", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "guide": { - "type": "string", - "title": "Guide", - "description": "The tour guide for the specified location", - "format": "markdown" - } - } - } - } - }, - { - "id": "createGuides", - "type": "map", - "configuration": {} - }, - { - "id": "curry-4", - "type": "curry", - "configuration": { - "$board": { - "kind": "board", - "board": { - "kits": [], - "edges": [ - { - "from": "guideGenerator", - "to": "output-4", - "out": "text", - "in": "guide" - }, - { - "from": "input-1", - "to": "guideTemplate", - "out": "location", - "in": "location" - }, - { - "from": "input-1", - "to": "guideGenerator", - "out": "generator", - "in": "$board" - }, - { - "from": "guideTemplate", - "to": "guideGenerator", - "out": "prompt", - "in": "text" - }, - { - "from": "input-3", - "to": "guideTemplate", - "out": "item", - "in": "activity" - } - ], - "nodes": [ - { - "id": "output-4", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "guide": { - "type": "string", - "title": "guide" - } - } - } - } - }, - { - "id": "guideGenerator", - "type": "invoke", - "configuration": { - "stopSequences": [ - "\n[City]" - ], - "useStreaming": false - } - }, - { - "id": "input-1", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "location": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "location", - "description": "The value to substitute for the parameter \"location\"" - }, - "generator": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": false, - "title": "Board", - "description": "The board to invoke. Can be a BoardCapability, a graph or a URL", - "behavior": [ - "board", - "config" - ] - } - }, - "required": [ - "location", - "generator" - ] - } - } - }, - { - "id": "guideTemplate", - "type": "promptTemplate", - "configuration": { - "template": "[City] Paris, France\n [Activity] Have a picnic in the Luxembourg Gardens\n [Experiential story] Grab a baguette, some cheese and bottle of wine and head over to Luxembourg Gardens. You'll enjoy an even stroll, a great chance to people watch, and a charming free evening that is quintessentially Parisian.\n\n [City] Madrid, Spain\n [Activity] See the Prado Museum\n [Experiential story] The Prado is an art lover's paradise. It is home to the largest collection of works by Goya, Velazquez, and El Greco. There are also works by Picasso, Monet, and Rembrandt. The Prado is a must-see for anyone visiting Madrid.\n\n [City] Tatooine\n [Activity] Catch a pod race\n [Experiential story] A pod race is a race of flying engines called pods. Pod racing is a dangerous sport and was very popular in the Outer Rim Territories before the Empire was formed.\n\n\n [City] {{location}}\n [Activity] {{activity}}\n [Experiential story]\n " - } - }, - { - "id": "input-3", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "item": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ], - "title": "activity", - "description": "The value to substitute for the parameter \"activity\"" - } - }, - "required": [ - "item" - ] - } - } - } - ], - "graphs": {} - } - } - }, - "metadata": { - "title": "Curry Params into Guide" - } - }, - { - "id": "fn-3", - "type": "runJavascript", - "configuration": { - "code": "const fn_3 = ({itinerary})=>{const list=itinerary.split(/[0-9]{1,2}\\)/).map(e=>e.trim()).filter(e=>e!==\"\");return{list}};", - "name": "fn_3", - "raw": true - } - }, - { - "id": "fn-6", - "type": "runJavascript", - "configuration": { - "code": "const fn_6 = ({location,activities,guides})=>{const guideList=guides.map(item=>item.guide);return{guide:`# ${location}\n${activities.map((activity,index)=>`## ${activity}\n${guideList[index]}\n\n`).join(\"\")}`}};", - "name": "fn_6", - "raw": true - } - }, - { - "id": "travelItinerary", - "type": "promptTemplate", - "configuration": { - "template": "[Place] Seattle, WA\n [Top ten place-based experiences with no duplicates]\n 1) See the city from the Space Needle\n 2) Watch the fish throwing at Pike Place Market\n 3) Add chewing gum to the The Gum Wall\n 4) Stroll the Chihuly Garden and Glass Museum\n 5) Take a selfie with the Fremont Troll\n 6) Walk the quad at the University of Washington\n 7) Watch the octopus feeding at the Seattle Aquarium\n 8) Learn about aviation history at the Museum of Flight\n 9) Wander the art at the Seattle Art Museum\n 10) See the baby gorilla at the Woodland Park Zoo\n\n [Place] Madrid, Spain\n [Top ten place-based experiences with no duplicates]\n 1) Stroll the Gran Via\n 2) See the Prado Museum\n 3) Attend a Real Madrid game\n 4) Stroll through the Mercado de San Miguel\n 5) Sip wine at the Bodega de Palacio\n 6) Go clubbing at the Chueca district\n 7) Shop at the El Rastro flea market\n 8) Take a selfie at the Puerta del Sol\n 9) Shop at the El Corte Ingles\n 10) Enjoy tapas and wine at La Latina\n\n [Place] Chicago, IL\n [Top ten place-based experiences with no duplicates]\n 1) Attend a Chicago Bulls game\n 2) Stroll the Magnificent Mile\n 3) Go to a museum at the Museum of Science and Industry\n 4) Stroll the Millennium Park\n 5) Visit the Willis Tower\n 6) See the Chicago River\n 7) Take a selfie at the Bean\n 8) Eat deep dish pizza at Giordano's\n 9) Shop at the Water Tower Place\n 10) See the Chicago Theatre\n\n [Place] {{location}}\n [Top ten place-based experiences with no duplicates]\n " - } - }, - { - "id": "travelItineraryGenerator", - "type": "invoke", - "configuration": { - "stopSequences": [ - "\n[Place]" - ], - "useStreaming": false - } - } - ] -} \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/webcam.ts b/packages/example-boards/src/boards/playground/webcam.ts deleted file mode 100644 index 11f572b1e9e..00000000000 --- a/packages/example-boards/src/boards/playground/webcam.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { annotate, array, board, input, object, output } from "@breadboard-ai/build"; -import { geminiText } from "@google-labs/gemini-kit"; - -const picture = input({ - title: "Image", - type: array( - annotate(object({}), { - behavior: ["llm-content"], - }) - ) -}); - -const prompt = input({ - title: "Prompt", - type: "string", - examples: ["Describe what you see in the picture"] -}); - -const llmResponse = geminiText({ - text: "unused", - // eslint-disable-next-line @typescript-eslint/no-explicit-any - context: picture as any, - model: "gemini-1.5-pro-latest", - systemInstruction: prompt -}); - -export default board({ - title: "Webcam", - description: "An example of using Gemini Kit's text node with a webcam", - version: "0.1.0", - inputs: { picture, prompt }, - outputs: { - text: output(llmResponse.outputs.text), - }, -}); \ No newline at end of file diff --git a/packages/example-boards/src/boards/playground/wiki-search-tool.bgl.json b/packages/example-boards/src/boards/playground/wiki-search-tool.bgl.json deleted file mode 100644 index 562aaed35a4..00000000000 --- a/packages/example-boards/src/boards/playground/wiki-search-tool.bgl.json +++ /dev/null @@ -1,195 +0,0 @@ -{ - "title": "Tool: Wiki Search", - "description": "A tool designed to take keywords, make use of the Wikipedia API, and get articles based on the keywords.", - "version": "0.0.1", - "nodes": [ - { - "type": "input", - "id": "input", - "configuration": { - "schema": { - "properties": { - "item": { - "type": "string", - "title": "SearchQuery", - "examples": [], - "description": "Enter keywords relating to the topic you wish to research" - } - }, - "type": "object", - "required": [] - } - }, - "metadata": { - "visual": { - "x": -195, - "y": 80, - "collapsed": false - } - } - }, - { - "id": "fetch-e26cfef6", - "type": "fetch", - "metadata": { - "visual": { - "x": 356, - "y": 195, - "collapsed": false - }, - "title": "Search Wikipedia", - "logLevel": "debug" - } - }, - { - "id": "urlTemplate-3e700b37", - "type": "urlTemplate", - "metadata": { - "visual": { - "x": 66.00000000000023, - "y": 126.99999999999989, - "collapsed": false - }, - "title": "Make URL", - "logLevel": "debug" - }, - "configuration": { - "template": "https://en.wikipedia.org/w/api.php?action=opensearch&search={query}&origin=*" - } - }, - { - "id": "output-cf0f1083", - "type": "output", - "metadata": { - "visual": { - "x": 1112.0000000000002, - "y": 352, - "collapsed": false - }, - "title": "output", - "logLevel": "debug" - }, - "configuration": { - "schema": { - "properties": { - "accumulator": { - "type": "array", - "title": "Result", - "examples": [], - "format": "markdown", - "description": "An array of article titles is returned" - } - }, - "type": "object", - "required": [] - } - } - }, - { - "id": "runJavascript-3002ef7c", - "type": "runJavascript", - "metadata": { - "visual": { - "x": 750.0000000000002, - "y": 299.99999999999966, - "collapsed": false - }, - "title": "Append Results", - "logLevel": "debug" - }, - "configuration": { - "code": "function run({accumulator = [], response}) {\n const links = response[3].map((link) => `${link.split(\"/\").slice(-1)[0]}`);\n return [...accumulator, ...links];\n}", - "name": "run", - "raw": false - } - } - ], - "edges": [ - { - "from": "urlTemplate-3e700b37", - "to": "fetch-e26cfef6", - "in": "url", - "out": "url" - }, - { - "from": "fetch-e26cfef6", - "to": "runJavascript-3002ef7c", - "out": "response", - "in": "response" - }, - { - "from": "runJavascript-3002ef7c", - "to": "output-cf0f1083", - "out": "result", - "in": "accumulator" - }, - { - "from": "input", - "to": "urlTemplate-3e700b37", - "out": "item", - "in": "query" - } - ], - "metadata": { - "comments": [ - { - "id": "comment-b6c2c866", - "text": "An input is made up of keywords, as you would when searching Wikipedia for an article", - "metadata": { - "visual": { - "x": -272, - "y": -1, - "collapsed": false - } - } - }, - { - "id": "comment-1ad1029d", - "text": "A template then creates a URL for the Wikipedia API to search", - "metadata": { - "visual": { - "x": 30, - "y": 70.99999999999989, - "collapsed": false - } - } - }, - { - "id": "comment-8f3cfe72", - "text": "The Wikipedia API is called and a list of up to 10 articles is found.", - "metadata": { - "visual": { - "x": 295.0000000000002, - "y": 135.9999999999999, - "collapsed": false - } - } - }, - { - "id": "comment-121b26b9", - "text": "The URLs are stripped for the page title and appended to an array of strings.", - "metadata": { - "visual": { - "x": 631, - "y": 241, - "collapsed": false - } - } - }, - { - "id": "comment-53a92521", - "text": "The array of strings is returned as the output.", - "metadata": { - "visual": { - "x": 987.0000000000002, - "y": 305, - "collapsed": false - } - } - } - ], - "tags": [ - "tool" - ] - } -} diff --git a/packages/example-boards/src/make-graphs.ts b/packages/example-boards/src/make-graphs.ts deleted file mode 100644 index c0256db3811..00000000000 --- a/packages/example-boards/src/make-graphs.ts +++ /dev/null @@ -1,179 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -// import { GraphDescriptor } from "@google-labs/breadboard"; -import { SerializableBoard, serialize } from "@breadboard-ai/build"; -import { - BoardReference, - BreadboardManifestBuilder, -} from "@breadboard-ai/manifest"; -import { - formatGraphDescriptor, - GraphDescriptor, -} from "@google-labs/breadboard"; -import { Dirent } from "fs"; -import { mkdir, readdir, writeFile, readFile, cp } from "fs/promises"; -import path from "path"; -import { fileURLToPath } from "url"; - -const MODULE_DIR: string = path.dirname(fileURLToPath(import.meta.url)); -const PATH: string = path.join(MODULE_DIR, "boards"); -const MANIFEST_PATH: string = path.join(MODULE_DIR, ".."); -const GRAPH_PATH: string = path.join(MODULE_DIR, "..", "example-boards"); - -await mkdir(GRAPH_PATH, { recursive: true }); - -async function findTsFiles(dir: string): Promise { - const files: Dirent[] = await readdir(dir, { withFileTypes: true }); - let tsFiles: string[] = []; - for (const file of files) { - const res: string = path.resolve(dir, file.name); - if (file.isDirectory()) { - tsFiles = tsFiles.concat(await findTsFiles(res)); - } else if (file.isFile() && file.name.endsWith(".ts")) { - tsFiles.push(res); - } - } - return tsFiles; -} - -async function findJsonFiles(dir: string): Promise { - const files: Dirent[] = await readdir(dir, { withFileTypes: true }); - let tsFiles: string[] = []; - for (const file of files) { - const res: string = path.resolve(dir, file.name); - if (file.isDirectory()) { - tsFiles = tsFiles.concat(await findJsonFiles(res)); - } else if (file.isFile() && file.name.endsWith(".json")) { - tsFiles.push(res); - } - } - return tsFiles; -} - -async function saveTypeScriptBoard( - filePath: string -): Promise { - try { - const module = await import(filePath); - - if (!module.default) { - // This is probably not a board or a board that doesn't want to be in the - // manifest. - return; - } - const relativePath: string = path.relative(PATH, filePath); - const baseName: string = path.basename(filePath); - const jsonFile: string = baseName.replace(".ts", ".json"); - - // Create corresponding directories based on the relative path - const graphDir: string = path.dirname(path.join(GRAPH_PATH, relativePath)); - - // Make sure the directories exist - await mkdir(graphDir, { recursive: true }); - - const url = `/example-boards/${relativePath.replace(".ts", ".json")}`; - if ("inputs" in module.default && "outputs" in module.default) { - // TODO(aomarks) Not a great way to detect build boards. - const board = module.default as SerializableBoard; - const manifest: BoardReference = { - title: module.default.title ?? "Untitled (build API)", - reference: url, - version: module.default.version ?? "", - }; - await writeFile( - path.join(graphDir, jsonFile), - JSON.stringify(serialize(board), null, 2) - ); - return manifest; - } else { - const board = module.default as SerializableBoard; - const manifest: BoardReference = { - title: module.default.title ?? "Untitled", - reference: url, - version: module.default.version ?? undefined, - }; - await writeFile( - path.join(graphDir, jsonFile), - JSON.stringify( - formatGraphDescriptor(JSON.parse(JSON.stringify(board))), - null, - 2 - ) - ); - return manifest; - } - } catch (e) { - if (e instanceof Error) { - console.error(e.stack); - } - throw new Error(`Error loading ${filePath}: ${e}`); - } -} - -async function saveJsonBoard( - filePath: string -): Promise { - const relativePath: string = path.relative(PATH, filePath); - const url = `/example-boards/${relativePath}`; - try { - // Create corresponding directories based on the relative path - const graphDir: string = path.dirname(path.join(GRAPH_PATH, relativePath)); - - // Make sure the directories exist - await mkdir(graphDir, { recursive: true }); - const destBoardPath = path.join(graphDir, path.basename(filePath)); - - const boardData = await readFile(filePath, { encoding: "utf-8" }); - const file = JSON.parse(boardData) as GraphDescriptor; - const manifest: BoardReference = { - title: file.title ?? "Untitled (Raw BGL File)", - reference: url, - version: file.version ?? "0.0.1", - tags: file.metadata?.tags ?? undefined, - }; - - await cp(filePath, destBoardPath); - - return manifest; - } catch (e) { - if (e instanceof Error) { - console.error(e.stack); - } - throw new Error(`Error loading ${filePath}: ${e}`); - } -} - -async function saveAllBoards(prefix: string): Promise { - const tsFiles = await findTsFiles(path.join(PATH, prefix)); - const jsonFiles = await findJsonFiles(path.join(PATH, prefix)); - const manifest: BreadboardManifestBuilder = new BreadboardManifestBuilder(); - - for (const file of tsFiles) { - const manifestEntry = await saveTypeScriptBoard(file); - if (!manifestEntry) continue; - // Avoid adding .local.json files to the manifest - if (!file.endsWith(".local.ts")) { - manifest.addBoard(manifestEntry); - } - } - - for (const file of jsonFiles) { - const manifestEntry = await saveJsonBoard(file); - if (!manifestEntry) continue; - // Avoid adding .local.json files to the manifest - if (!file.endsWith(".local.json")) { - manifest.addBoard(manifestEntry); - } - } - - await writeFile( - path.join(MANIFEST_PATH, `${prefix}-boards.json`), - JSON.stringify(manifest, null, 2) - ); -} - -await Promise.all([saveAllBoards("playground"), saveAllBoards("examples")]); diff --git a/packages/example-boards/src/utils/countryCodes.ts b/packages/example-boards/src/utils/countryCodes.ts deleted file mode 100644 index ba47f395c33..00000000000 --- a/packages/example-boards/src/utils/countryCodes.ts +++ /dev/null @@ -1,134 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export const countryCodes = [ - "AD", - "AL", - "AM", - "AR", - "AT", - "AU", - "AX", - "BA", - "BB", - "BE", - "BG", - "BJ", - "BO", - "BR", - "BS", - "BW", - "BY", - "BZ", - "CA", - "CH", - "CL", - "CN", - "CO", - "CR", - "CU", - "CY", - "CZ", - "DE", - "DK", - "DO", - "EC", - "EE", - "EG", - "ES", - "FI", - "FO", - "FR", - "GA", - "GB", - "GD", - "GE", - "GG", - "GI", - "GL", - "GM", - "GR", - "GT", - "GY", - "HK", - "HN", - "HR", - "HT", - "HU", - "ID", - "IE", - "IL", - "IM", - "IN", - "IS", - "IT", - "JE", - "JM", - "JP", - "KE", - "KG", - "KH", - "KR", - "KW", - "KZ", - "LA", - "LI", - "LK", - "LS", - "LT", - "LU", - "LV", - "MA", - "MC", - "MD", - "ME", - "MG", - "MK", - "MN", - "MS", - "MT", - "MX", - "MY", - "MZ", - "NA", - "NE", - "NG", - "NI", - "NL", - "NO", - "NZ", - "PA", - "PE", - "PG", - "PH", - "PK", - "PL", - "PR", - "PT", - "PY", - "RO", - "RS", - "RU", - "RW", - "SE", - "SG", - "SI", - "SJ", - "SK", - "SM", - "SR", - "SV", - "TN", - "TR", - "UA", - "US", - "UY", - "VA", - "VE", - "VN", - "ZA", - "ZW", -] as const; diff --git a/packages/example-boards/src/utils/kit-loader.ts b/packages/example-boards/src/utils/kit-loader.ts deleted file mode 100644 index dbe554d50e8..00000000000 --- a/packages/example-boards/src/utils/kit-loader.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { KitConstructor, Kit, asRuntimeKit } from "@google-labs/breadboard"; -import { load } from "@google-labs/breadboard/kits"; - -export const loadKits = async (kiConstructors: KitConstructor[]) => { - const loadedKits = kiConstructors.map((kitConstructor) => - asRuntimeKit(kitConstructor) - ); - - const base = new URL(`${self.location.origin}/kits.json`); - const response = await fetch(base); - const kitList = await response.json(); - - const kits = await Promise.all( - kitList.map(async (kitURL: string) => { - // workaround for vite prod/dev mode difference - if (kitURL.endsWith(".js") && import.meta.env.DEV) { - kitURL = `/src/${kitURL.replace(/\.js$/, ".ts")}`; - } - return await load(new URL(kitURL, base)); - }) - ); - - return [...loadedKits, ...kits]; -}; diff --git a/packages/example-boards/src/utils/pop.ts b/packages/example-boards/src/utils/pop.ts deleted file mode 100644 index 0ced21c6439..00000000000 --- a/packages/example-boards/src/utils/pop.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { code } from "@google-labs/breadboard"; - -export const pop = code< - { array: object[] }, - { array?: object[]; item?: unknown } ->((inputs) => { - const { array } = inputs; - const [item, ...rest] = array; - if (item) { - return { array: rest, item }; - } - return {}; -}); diff --git a/packages/example-boards/src/vite-env.d.ts b/packages/example-boards/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a00..00000000000 --- a/packages/example-boards/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/packages/example-boards/tsconfig.json b/packages/example-boards/tsconfig.json deleted file mode 100644 index 8019032027f..00000000000 --- a/packages/example-boards/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "ESNext", - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - "experimentalDecorators": true, - "useDefineForClassFields": false, - "outDir": "build", - - /* Bundler mode */ - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src/**/*.ts"], - "exclude": ["build"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/gemini-kit/.eslintrc b/packages/gemini-kit/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/gemini-kit/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/gemini-kit/.gitignore b/packages/gemini-kit/.gitignore deleted file mode 100644 index 70e058ac95d..00000000000 --- a/packages/gemini-kit/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# TODO(aomarks) We probably shouldn't check in these graphs, but it's useful -# temporarily because it provides a good record of what changes in the BGL -# serialization upon upgrading to the new API. -# graphs/ \ No newline at end of file diff --git a/packages/gemini-kit/.npmignore b/packages/gemini-kit/.npmignore deleted file mode 100644 index 7ddb2133685..00000000000 --- a/packages/gemini-kit/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -tsconfig.tsbuildinfo diff --git a/packages/gemini-kit/CHANGELOG.md b/packages/gemini-kit/CHANGELOG.md deleted file mode 100644 index 25ea47815b3..00000000000 --- a/packages/gemini-kit/CHANGELOG.md +++ /dev/null @@ -1,608 +0,0 @@ -# @google-labs/gemini-kit - -## 0.8.0 - -### Minor Changes - -- 4c03455: Introduce Specialist 2 and make Content component support LLM Content. - -### Patch Changes - -- 323216f: Expand the JSON schema type for gemini text instruction -- 54c8197: Make build API kit function async -- f5d3111: Add gemini-1.5-pro-exp-0801 to gemini model enum -- e63b5dd: Polish Specialist and Content. -- 7fdf9c2: Add "gemini-1.5-pro-exp-0827" to the choices in Gemini-calling components. -- Updated dependencies [49e2740] -- Updated dependencies [54c8197] -- Updated dependencies [703f17d] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [8f9fddf] -- Updated dependencies [2fa05f0] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [f71bcfb] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [3188607] -- Updated dependencies [9797718] -- Updated dependencies [88298d5] -- Updated dependencies [b673bfa] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [feeed7a] -- Updated dependencies [4cc71ee] -- Updated dependencies [8330f0c] -- Updated dependencies [a039d2e] -- Updated dependencies [1423647] -- Updated dependencies [9783ba8] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [91fe8bb] -- Updated dependencies [100fc95] -- Updated dependencies [4423c35] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [5834c81] -- Updated dependencies [d7606d3] -- Updated dependencies [0ef793f] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] -- Updated dependencies [9c04caa] - - @breadboard-ai/build@0.10.0 - - @google-labs/core-kit@0.15.0 - - @google-labs/breadboard@0.27.0 - - @google-labs/template-kit@0.3.10 - -## 0.7.0 - -### Minor Changes - -- 13c27cb: Fully migrate to Build API -- 3cb60e9: Remove gemini-vision. Use multi-modal instead. - -### Patch Changes - -- Updated dependencies [bbcdd2d] -- Updated dependencies [9ed58cf] -- Updated dependencies [7f2ef33] -- Updated dependencies [85fb144] -- Updated dependencies [7d46a63] -- Updated dependencies [bac2e35] -- Updated dependencies [ec2fedd] - - @breadboard-ai/build@0.9.1 - - @google-labs/core-kit@0.14.1 - - @google-labs/breadboard@0.26.0 - - @google-labs/template-kit@0.3.9 - -## 0.6.0 - -### Minor Changes - -- 78a6bcf: Remove example inputs from gemini-generator - -### Patch Changes - -- cc5f4b6: Updates for new board function API in build package -- Updated dependencies [cc5f4b6] -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [a940b87] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [374ea85] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [f93ec06] -- Updated dependencies [cc5f4b6] -- Updated dependencies [398bf4f] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [ee1f9ca] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @breadboard-ai/build@0.9.0 - - @google-labs/breadboard@0.25.0 - - @google-labs/core-kit@0.14.0 - - @google-labs/node-nursery-web@1.3.0 - - @google-labs/json-kit@0.3.6 - - @google-labs/template-kit@0.3.8 - -## 0.5.4 - -### Patch Changes - -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [1dc645a] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [c04cff0] -- Updated dependencies [d88c37b] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - - @google-labs/node-nursery-web@1.2.0 - - @google-labs/core-kit@0.13.0 - - @breadboard-ai/build@0.8.1 - - @google-labs/json-kit@0.3.5 - - @google-labs/template-kit@0.3.7 - -## 0.5.3 - -### Patch Changes - -- 0519ebb: Export geminiText from gemini package -- 9a2ffab: Unpin @breadboard-ai/build dependency from being overly constrained -- Updated dependencies [ad8aa22] -- Updated dependencies [1e1be2a] -- Updated dependencies [6d2939e] -- Updated dependencies [15b6171] -- Updated dependencies [5c5b665] -- Updated dependencies [2b094a3] -- Updated dependencies [fa93c3f] -- Updated dependencies [f78ec0a] -- Updated dependencies [215bd15] -- Updated dependencies [2b9ef5b] -- Updated dependencies [a0852df] -- Updated dependencies [7298a47] -- Updated dependencies [ea7e2a1] -- Updated dependencies [8edcbc0] -- Updated dependencies [8db38aa] -- Updated dependencies [9a2ffab] -- Updated dependencies [b99472b] -- Updated dependencies [4bfaec5] -- Updated dependencies [2312443] -- Updated dependencies [b76f9a1] -- Updated dependencies [6ffa89c] -- Updated dependencies [15ae381] - - @breadboard-ai/build@0.8.0 - - @google-labs/breadboard@0.23.0 - - @google-labs/core-kit@0.12.0 - - @google-labs/template-kit@0.3.6 - - @google-labs/json-kit@0.3.4 - - @google-labs/node-nursery-web@1.1.6 - -## 0.5.2 - -### Patch Changes - -- Updated dependencies [a925cf0] -- Updated dependencies [f4d2416] -- Updated dependencies [bc94299] -- Updated dependencies [166f290] -- Updated dependencies [da43bb5] -- Updated dependencies [5cf08f1] -- Updated dependencies [9d93cf8] -- Updated dependencies [9d93cf8] -- Updated dependencies [ffbf163] -- Updated dependencies [8928fb7] -- Updated dependencies [9d93cf8] -- Updated dependencies [d6706f2] -- Updated dependencies [5447426] -- Updated dependencies [26e1099] -- Updated dependencies [7e1f01c] -- Updated dependencies [a9def5c] - - @google-labs/breadboard@0.22.0 - - @google-labs/core-kit@0.11.0 - - @breadboard-ai/build@0.7.1 - - @google-labs/json-kit@0.3.3 - - @google-labs/node-nursery-web@1.1.5 - - @google-labs/template-kit@0.3.5 - -## 0.5.1 - -### Patch Changes - -- 29774aa: Update dependency package versions. -- Updated dependencies [29774aa] - - @google-labs/template-kit@0.3.4 - - @google-labs/core-kit@0.10.1 - - @google-labs/json-kit@0.3.2 - -## 0.5.0 - -### Minor Changes - -- 14853d5: Add Gemini Nano node. -- 71f3366: Added `flash`, removed `ultra` and `1.0-pro` (they don't have all the latest stuff). - -### Patch Changes - -- a8bb460: Teach Gemini Generator to report errors correctly. -- 5f09b1d: Better error messages and descriptions, also deprecate `vision`. -- Updated dependencies [5a55b7d] -- Updated dependencies [74ade20] -- Updated dependencies [c27c176] -- Updated dependencies [59dd0f5] -- Updated dependencies [4e66406] -- Updated dependencies [417323c] -- Updated dependencies [b3aa884] -- Updated dependencies [85bbc00] -- Updated dependencies [00825d5] -- Updated dependencies [3d7b4a7] -- Updated dependencies [7af14cf] -- Updated dependencies [4db3ab7] -- Updated dependencies [d9b76bd] -- Updated dependencies [fea8967] -- Updated dependencies [778f7aa] -- Updated dependencies [808f5e2] -- Updated dependencies [e0fdbc3] -- Updated dependencies [54b03b9] -- Updated dependencies [810d7fd] -- Updated dependencies [14853d5] -- Updated dependencies [5a0afe4] -- Updated dependencies [8798514] -- Updated dependencies [eb64b9a] -- Updated dependencies [6fdd89e] -- Updated dependencies [c82138d] -- Updated dependencies [32a48a3] -- Updated dependencies [cd73b17] -- Updated dependencies [81d82fe] -- Updated dependencies [2a7531b] -- Updated dependencies [7c1b4cb] -- Updated dependencies [702cfe1] -- Updated dependencies [bebd96e] -- Updated dependencies [91cb723] -- Updated dependencies [3e10f0f] -- Updated dependencies [0e54e55] -- Updated dependencies [c53ca01] -- Updated dependencies [6ada218] -- Updated dependencies [4c681cb] -- Updated dependencies [fb2e584] -- Updated dependencies [9491266] -- Updated dependencies [0e76614] -- Updated dependencies [2ace620] -- Updated dependencies [c5f8e4f] -- Updated dependencies [fcef799] -- Updated dependencies [37418d9] -- Updated dependencies [26556b6] -- Updated dependencies [083f69c] -- Updated dependencies [5f09b1d] -- Updated dependencies [b75a43e] -- Updated dependencies [6fdd89e] -- Updated dependencies [5b03d96] -- Updated dependencies [f0d8d67] -- Updated dependencies [9b1513a] -- Updated dependencies [510e198] -- Updated dependencies [836389d] -- Updated dependencies [225c7cc] -- Updated dependencies [9491266] -- Updated dependencies [06c3f57] - - @google-labs/breadboard@0.21.0 - - @google-labs/core-kit@0.10.0 - - @breadboard-ai/build@0.7.0 - - @google-labs/template-kit@0.3.3 - - @google-labs/json-kit@0.3.1 - - @google-labs/node-nursery-web@1.1.4 - -## 0.4.0 - -### Minor Changes - -- c69f1c5: Teach Looper how to plan and add `responseMimeType` to Gemini API. -- 3f0ce31: Teach Gemini Kit about "tool" role. -- 8bef702: Convert gemini-text to new Breadboard API -- bfdb36a: Remove streaming support for now because it's not working anyway. - -### Patch Changes - -- ffd2e8e: The core-kit code helper function now behaves exactly like the one in breadboard-ai in terms of the function name it selects for the code. -- bfdb36a: Add IDs to nodes for BGL clarity -- Updated dependencies [8097177] -- Updated dependencies [8774855] -- Updated dependencies [1b596d4] -- Updated dependencies [29eda71] -- Updated dependencies [4957dc5] -- Updated dependencies [7936d8b] -- Updated dependencies [f60cb06] -- Updated dependencies [cec6d54] -- Updated dependencies [87eb8fe] -- Updated dependencies [f97a4d5] -- Updated dependencies [60a18c5] -- Updated dependencies [b0ed6f3] -- Updated dependencies [4957dc5] -- Updated dependencies [a209c51] -- Updated dependencies [cdcbcdb] -- Updated dependencies [3397974] -- Updated dependencies [7368fdd] -- Updated dependencies [c9c0e06] -- Updated dependencies [c1acf24] -- Updated dependencies [af54870] -- Updated dependencies [3920805] -- Updated dependencies [ab9a4ce] -- Updated dependencies [3b2bb4a] -- Updated dependencies [a35406c] -- Updated dependencies [31cf016] -- Updated dependencies [ab43276] -- Updated dependencies [477e6e6] -- Updated dependencies [cdcbcdb] -- Updated dependencies [ee85b67] -- Updated dependencies [791ec2a] -- Updated dependencies [c0293c9] -- Updated dependencies [1d29493] -- Updated dependencies [b6f5644] -- Updated dependencies [f870bdd] -- Updated dependencies [43edef6] - - @google-labs/breadboard@0.20.0 - - @google-labs/core-kit@0.9.0 - - @breadboard-ai/build@0.6.0 - - @google-labs/json-kit@0.3.0 - - @google-labs/node-nursery-web@1.1.3 - - @google-labs/template-kit@0.3.2 - -## 0.3.1 - -### Patch Changes - -- Updated dependencies [63eb779] - - @google-labs/breadboard@0.19.0 - - @google-labs/core-kit@0.8.1 - - @google-labs/json-kit@0.2.2 - - @google-labs/node-nursery-web@1.1.2 - - @google-labs/template-kit@0.3.1 - -## 0.3.0 - -### Minor Changes - -- 691f3d6: Give gemini-generator an overhaul, adding proper system instruction support and safety settings. -- e736f37: Remove deprecated input-multipart -- 24230c1: Introduce LLM Content Editor - -### Patch Changes - -- f2eda0b: Fix lots of bugs around Tool Worker. -- 5369037: Fix JSONata calls to account for LLM Content -- Updated dependencies [cef20ca] -- Updated dependencies [18b9f34] -- Updated dependencies [d7829a1] -- Updated dependencies [fbf7a83] -- Updated dependencies [54baba8] -- Updated dependencies [49c3aa1] -- Updated dependencies [cdc23bb] -- Updated dependencies [416aed2] -- Updated dependencies [fefd109] -- Updated dependencies [a1fcaea] -- Updated dependencies [1aa96c6] -- Updated dependencies [c3ed6a7] -- Updated dependencies [34d9c6d] -- Updated dependencies [3d48482] -- Updated dependencies [c117d4f] -- Updated dependencies [f2eda0b] -- Updated dependencies [626139b] -- Updated dependencies [bd44e29] -- Updated dependencies [43da00a] -- Updated dependencies [776f043] -- Updated dependencies [c3587e1] -- Updated dependencies [34d9c6d] -- Updated dependencies [4d6ce42] -- Updated dependencies [3f9507d] - - @google-labs/breadboard@0.18.0 - - @google-labs/template-kit@0.3.0 - - @google-labs/core-kit@0.8.0 - - @google-labs/node-nursery-web@1.1.1 - - @google-labs/json-kit@0.2.1 - -## 0.2.0 - -### Minor Changes - -- 55ed307: Add system instruction support. - -### Patch Changes - -- Updated dependencies [b244fba] -- Updated dependencies [c3cb25f] -- Updated dependencies [ae79e4a] -- Updated dependencies [72c5c6b] -- Updated dependencies [0831735] -- Updated dependencies [dd810dd] -- Updated dependencies [c5ba396] -- Updated dependencies [7bafa40] -- Updated dependencies [2932f4b] -- Updated dependencies [51159c4] -- Updated dependencies [cffceb9] -- Updated dependencies [6f9ba52] -- Updated dependencies [914353c] -- Updated dependencies [d60f38b] -- Updated dependencies [5602f1e] - - @google-labs/template-kit@0.2.6 - - @google-labs/breadboard@0.17.0 - - @google-labs/core-kit@0.7.0 - - @google-labs/node-nursery-web@1.1.0 - - @google-labs/json-kit@0.2.0 - -## 0.1.8 - -### Patch Changes - -- Updated dependencies [ad9c233] -- Updated dependencies [65d869b] -- Updated dependencies [417cdf5] -- Updated dependencies [cf0ee4f] -- Updated dependencies [43cbed7] -- Updated dependencies [ff6433c] -- Updated dependencies [5382365] -- Updated dependencies [0e7f106] -- Updated dependencies [9ea6ba0] -- Updated dependencies [ffd2a6c] -- Updated dependencies [9d19852] - - @google-labs/breadboard@0.16.0 - - @google-labs/core-kit@0.6.0 - - @google-labs/json-kit@0.1.5 - - @google-labs/node-nursery-web@1.0.8 - - @google-labs/template-kit@0.2.5 - -## 0.1.7 - -### Patch Changes - -- Updated dependencies [76da09d] -- Updated dependencies [938015d] -- Updated dependencies [182a546] - - @google-labs/breadboard@0.15.0 - - @google-labs/core-kit@0.5.3 - - @google-labs/json-kit@0.1.4 - - @google-labs/node-nursery-web@1.0.7 - - @google-labs/template-kit@0.2.4 - -## 0.1.6 - -### Patch Changes - -- Updated dependencies [e8d0737] - - @google-labs/breadboard@0.14.0 - - @google-labs/core-kit@0.5.2 - - @google-labs/json-kit@0.1.3 - - @google-labs/node-nursery-web@1.0.6 - - @google-labs/template-kit@0.2.3 - -## 0.1.5 - -### Patch Changes - -- 646680a: Add gemini-pro-1.5 to the list of models. -- Updated dependencies [faf1e12] -- Updated dependencies [51a38c0] -- Updated dependencies [d49b80e] -- Updated dependencies [9326bd7] -- Updated dependencies [fbad949] - - @google-labs/breadboard@0.13.0 - - @google-labs/core-kit@0.5.1 - - @google-labs/json-kit@0.1.2 - - @google-labs/node-nursery-web@1.0.5 - - @google-labs/template-kit@0.2.2 - -## 0.1.4 - -### Patch Changes - -- 99446b8: Various quality improvements to schemas and Graph Inspector API. -- ad5c1be: Introduce Tool Worker node in Agent Kit. -- Updated dependencies [f73c637] -- Updated dependencies [99446b8] -- Updated dependencies [866fc36] -- Updated dependencies [a8bab08] -- Updated dependencies [decfa29] -- Updated dependencies [f005b3b] -- Updated dependencies [49c25aa] -- Updated dependencies [dcfdc37] -- Updated dependencies [d971aad] -- Updated dependencies [048e8ec] -- Updated dependencies [dc35601] -- Updated dependencies [9cda2ff] -- Updated dependencies [60bd63c] -- Updated dependencies [764ccda] -- Updated dependencies [04d5420] -- Updated dependencies [56b90a4] -- Updated dependencies [1b48826] -- Updated dependencies [e648f64] -- Updated dependencies [ad5c1be] -- Updated dependencies [4a4a1f6] -- Updated dependencies [bac9bb1] -- Updated dependencies [3e8cfcf] -- Updated dependencies [986af39] -- Updated dependencies [3c497b0] -- Updated dependencies [5bc47be] -- Updated dependencies [eabd97b] -- Updated dependencies [2008f69] -- Updated dependencies [c0f785a] -- Updated dependencies [a8fc3f3] -- Updated dependencies [32cfbaf] -- Updated dependencies [8dc4e00] -- Updated dependencies [6438930] -- Updated dependencies [dd2cce6] -- Updated dependencies [cac4f4f] -- Updated dependencies [b1fc53b] -- Updated dependencies [ef05634] -- Updated dependencies [c208cfc] - - @google-labs/core-kit@0.5.0 - - @google-labs/breadboard@0.12.0 - - @google-labs/json-kit@0.1.1 - - @google-labs/node-nursery-web@1.0.4 - - @google-labs/template-kit@0.2.1 - -## 0.1.3 - -### Patch Changes - -- Updated dependencies [07e66bf] -- Updated dependencies [26367fe] - - @google-labs/breadboard@0.11.2 - - @google-labs/core-kit@0.4.0 - -## 0.1.2 - -### Patch Changes - -- Updated dependencies [c19513e] -- Updated dependencies [a9daeda] -- Updated dependencies [2237a4c] -- Updated dependencies [bd68ebd] -- Updated dependencies [9a76a87] -- Updated dependencies [ea652f3] -- Updated dependencies [56954c1] -- Updated dependencies [0085ee2] -- Updated dependencies [0ef9ec5] -- Updated dependencies [ee00249] -- Updated dependencies [c13513f] -- Updated dependencies [56ccae5] -- Updated dependencies [4920d90] -- Updated dependencies [10a8129] -- Updated dependencies [c804ccc] -- Updated dependencies [5a65297] -- Updated dependencies [53406ad] -- Updated dependencies [4c5b853] -- Updated dependencies [3f3f090] -- Updated dependencies [d7a7903] -- Updated dependencies [4401a98] -- Updated dependencies [f6e9b2c] - - @google-labs/breadboard@0.11.0 - - @google-labs/core-kit@0.3.0 - - @google-labs/json-kit@0.1.0 - - @google-labs/template-kit@0.2.0 - - @google-labs/node-nursery-web@1.0.3 - -## 0.1.1 - -### Patch Changes - -- d22d998: Make Gemini Kit public. - -## 0.1.0 - -### Minor Changes - -- fb1c768: Introduce Gemini Kit. - -### Patch Changes - -- 3e56a4f: Added a few TSDoc comments to kits for Intellisense. -- Updated dependencies [3e56a4f] -- Updated dependencies [fb1c768] - - @google-labs/template-kit@0.1.4 - - @google-labs/core-kit@0.2.2 - - @google-labs/breadboard@0.10.1 diff --git a/packages/gemini-kit/README.md b/packages/gemini-kit/README.md deleted file mode 100644 index 2021687783b..00000000000 --- a/packages/gemini-kit/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Breadboard Gemini Kit - -A collection of components that are useful for working with the Gemini API. diff --git a/packages/gemini-kit/graphs/gemini-generator.json b/packages/gemini-kit/graphs/gemini-generator.json deleted file mode 100644 index 661cb9cadfc..00000000000 --- a/packages/gemini-kit/graphs/gemini-generator.json +++ /dev/null @@ -1,1949 +0,0 @@ -{ - "title": "Gemini Generator", - "description": "Generates text using the Gemini API.", - "version": "0.1.0", - "edges": [ - { - "from": "choose-method", - "to": "make-url", - "out": "method", - "in": "method" - }, - { - "from": "choose-method", - "to": "make-url", - "out": "sseOption", - "in": "sseOption" - }, - { - "from": "collect-errors", - "to": "count-retries", - "out": "error", - "in": "error" - }, - { - "from": "collect-errors", - "to": "count-retries", - "out": "retry", - "in": "retry" - }, - { - "from": "count-retries", - "to": "collect-errors", - "out": "retry", - "in": "retry" - }, - { - "from": "count-retries", - "to": "make-body", - "out": "context", - "in": "context" - }, - { - "from": "count-retries", - "to": "make-body", - "out": "model", - "in": "model" - }, - { - "from": "count-retries", - "to": "make-body", - "out": "responseMimeType", - "in": "responseMimeType" - }, - { - "from": "count-retries", - "to": "make-body", - "out": "safetySettings", - "in": "safetySettings" - }, - { - "from": "count-retries", - "to": "make-body", - "out": "stopSequences", - "in": "stopSequences" - }, - { - "from": "count-retries", - "to": "make-body", - "out": "systemInstruction", - "in": "systemInstruction" - }, - { - "from": "count-retries", - "to": "make-body", - "out": "text", - "in": "text" - }, - { - "from": "count-retries", - "to": "make-body", - "out": "tools", - "in": "tools" - }, - { - "from": "fetch-gemini-api", - "to": "collect-errors", - "out": "$error", - "in": "error" - }, - { - "from": "fetch-gemini-api", - "to": "format-response", - "out": "response", - "in": "response" - }, - { - "from": "format-response", - "to": "collect-errors", - "out": "$error", - "in": "error" - }, - { - "from": "format-response", - "to": "content-output", - "out": "context", - "in": "context" - }, - { - "from": "format-response", - "to": "content-output", - "out": "text", - "in": "text" - }, - { - "from": "format-response", - "to": "tool-call-output", - "out": "context", - "in": "context" - }, - { - "from": "GEMINI_KEY-secret", - "to": "make-url", - "out": "GEMINI_KEY", - "in": "GEMINI_KEY" - }, - { - "from": "inputs", - "to": "choose-method", - "out": "useStreaming", - "in": "useStreaming" - }, - { - "from": "inputs", - "to": "count-retries", - "out": "context", - "in": "context", - "constant": true - }, - { - "from": "inputs", - "to": "count-retries", - "out": "model", - "in": "model", - "constant": true - }, - { - "from": "inputs", - "to": "count-retries", - "out": "responseMimeType", - "in": "responseMimeType", - "constant": true - }, - { - "from": "inputs", - "to": "count-retries", - "out": "retry", - "in": "retry" - }, - { - "from": "inputs", - "to": "count-retries", - "out": "safetySettings", - "in": "safetySettings", - "constant": true - }, - { - "from": "inputs", - "to": "count-retries", - "out": "stopSequences", - "in": "stopSequences", - "constant": true - }, - { - "from": "inputs", - "to": "count-retries", - "out": "systemInstruction", - "in": "systemInstruction", - "constant": true - }, - { - "from": "inputs", - "to": "count-retries", - "out": "text", - "in": "text", - "constant": true - }, - { - "from": "inputs", - "to": "count-retries", - "out": "tools", - "in": "tools", - "constant": true - }, - { - "from": "inputs", - "to": "fetch-gemini-api", - "out": "useStreaming", - "in": "stream", - "constant": true - }, - { - "from": "inputs", - "to": "make-url", - "out": "model", - "in": "model" - }, - { - "from": "make-body", - "to": "fetch-gemini-api", - "out": "result", - "in": "body" - }, - { - "from": "make-url", - "to": "fetch-gemini-api", - "out": "url", - "in": "url", - "constant": true - } - ], - "nodes": [ - { - "id": "inputs", - "type": "input", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "title": "Context", - "description": "An array of messages to use as conversation context", - "default": "[]", - "items": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "model", - "user", - "tool", - "$metadata" - ] - }, - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "inlineData": { - "type": "object", - "properties": { - "mimeType": { - "type": "string", - "enum": [ - "image/png", - "image/jpeg", - "image/heic", - "image/heif", - "image/webp" - ] - }, - "data": { - "type": "string" - } - }, - "required": [ - "mimeType", - "data" - ], - "additionalProperties": false - } - }, - "required": [ - "inlineData" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_call": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "function_call" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_response": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "response": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "name", - "response" - ], - "additionalProperties": false - } - }, - "required": [ - "function_response" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "role", - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - } - }, - "model": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Model", - "description": "The model to use for generation", - "default": "gemini-1.5-flash-latest", - "examples": [ - "gemini-1.5-flash-latest" - ], - "enum": [ - "gemini-1.5-flash-latest", - "gemini-1.5-pro-latest" - ] - }, - "responseMimeType": { - "type": "string", - "behavior": [ - "config" - ], - "title": "Response MIME Type", - "description": "Output response mimetype of the generated text.", - "default": "text/plain", - "examples": [ - "text/plain" - ], - "enum": [ - "text/plain", - "application/json" - ] - }, - "retry": { - "type": "number", - "behavior": [ - "config" - ], - "title": "Retry Count", - "description": "The number of times to retry the LLM call in case of failure", - "default": "1" - }, - "safetySettings": { - "type": "array", - "behavior": [ - "config" - ], - "title": "Safety Settings", - "description": "The safety settings object (see https://ai.google.dev/api/rest/v1beta/SafetySetting for more information)", - "default": "[]", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string" - }, - "threshold": { - "type": "string" - } - }, - "required": [ - "category", - "threshold" - ], - "additionalProperties": false - } - }, - "stopSequences": { - "type": "array", - "behavior": [ - "config" - ], - "title": "Stop Sequences", - "description": "An array of strings that will stop the output", - "default": "[]", - "items": { - "type": "string" - } - }, - "systemInstruction": { - "type": "string", - "behavior": [ - "config" - ], - "title": "System Instruction", - "description": "Give the model additional context to understand the task, provide more customized responses, and adhere to specific guidelines over the full user interaction.", - "default": "" - }, - "text": { - "type": "string", - "title": "Text", - "description": "The text to generate", - "default": "" - }, - "tools": { - "type": "array", - "title": "Tools", - "description": "An array of functions to use for tool-calling", - "default": "[]", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "parameters": { - "type": "object" - } - }, - "required": [ - "name", - "description", - "parameters" - ], - "additionalProperties": false - } - }, - "useStreaming": { - "type": "boolean", - "behavior": [ - "deprecated" - ], - "title": "Stream Output", - "description": "Whether to stream the output", - "default": "false" - } - }, - "required": [] - } - }, - "metadata": { - "title": "Input Parameters", - "description": "Collecting input parameters" - } - }, - { - "id": "content-output", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "object", - "title": "Context", - "description": "The conversation context", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false - }, - "text": { - "type": "string", - "title": "Text", - "description": "The generated text" - } - }, - "required": [ - "context", - "text" - ] - } - }, - "metadata": { - "title": "Content Output", - "description": "Outputting content" - } - }, - { - "id": "tool-call-output", - "type": "output", - "configuration": { - "schema": { - "type": "object", - "properties": { - "context": { - "type": "object", - "title": "Context", - "description": "The conversation context", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false - } - }, - "required": [ - "context" - ] - } - }, - "metadata": { - "title": "Tool Call Output", - "description": "Outputting a tool call" - } - }, - { - "id": "choose-method", - "type": "runJavascript", - "configuration": { - "code": "const choose_method = ({ useStreaming }) => {\n const method = useStreaming ? \"streamGenerateContent\" : \"generateContent\";\n const sseOption = useStreaming ? \"&alt=sse\" : \"\";\n return { method, sseOption };\n};", - "inputSchema": { - "type": "object", - "properties": { - "useStreaming": { - "type": "boolean", - "behavior": [ - "deprecated" - ] - } - } - }, - "name": "choose_method", - "outputSchema": { - "type": "object", - "properties": { - "method": { - "type": "string", - "enum": [ - "streamGenerateContent", - "generateContent" - ] - }, - "sseOption": { - "type": "string" - } - } - }, - "raw": true - }, - "metadata": { - "title": "Choose Method", - "description": "Choosing the right Gemini API method" - } - }, - { - "id": "collect-errors", - "type": "passthrough", - "configuration": {}, - "metadata": { - "title": "Collect Errors", - "description": "Collecting the error from Gemini API" - } - }, - { - "id": "count-retries", - "type": "runJavascript", - "configuration": { - "code": "const count_retries = ({ retry, error, ...rest }) => {\n retry = retry || 0;\n let errorResponse = {};\n try {\n errorResponse = JSON.parse(error?.error?.message || \"null\");\n }\n catch (e) {\n // Ignore the error\n }\n const errorCode = errorResponse?.error?.code;\n if (errorCode) {\n // Retry won't help with 404, 429 or 400, because these are either the\n // caller's problem or in case of 429, retries are actually doing more harm\n // than good.\n const retryWontHelp = errorCode == 400 || errorCode == 429 || errorCode == 404;\n if (retryWontHelp) {\n // TODO(aomarks) We don't have `code` in the general $error type, and we\n // probably shouldn't since there are all kind of possible error shapes.\n // There should probably be a way to set the schema for $error to any\n // sub-type of the general one on a node-by-node basis. For now we just\n // cast to pretend `code` isn't there.\n return { $error: error };\n }\n // The \"-1\" value is something that responseFormatter sends when empty\n // response is encountered.\n if (errorCode == -1) {\n return { $error: error };\n }\n }\n if (retry < 0) {\n return {\n $error: \"Exceeded retry count, was unable to produce a useful response from the Gemini API.\",\n };\n }\n retry = retry - 1;\n return { ...rest, retry };\n};", - "error": {}, - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "model", - "user", - "tool", - "$metadata" - ] - }, - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "inlineData": { - "type": "object", - "properties": { - "mimeType": { - "type": "string", - "enum": [ - "image/png", - "image/jpeg", - "image/heic", - "image/heif", - "image/webp" - ] - }, - "data": { - "type": "string" - } - }, - "required": [ - "mimeType", - "data" - ], - "additionalProperties": false - } - }, - "required": [ - "inlineData" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_call": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "function_call" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_response": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "response": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "name", - "response" - ], - "additionalProperties": false - } - }, - "required": [ - "function_response" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "role", - "parts" - ], - "additionalProperties": false, - "behavior": [ - "llm-content" - ] - } - }, - "systemInstruction": { - "type": "string", - "behavior": [ - "config" - ] - }, - "text": { - "type": "string" - }, - "model": { - "type": "string", - "enum": [ - "gemini-1.5-flash-latest", - "gemini-1.5-pro-latest" - ], - "behavior": [ - "config" - ] - }, - "tools": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "parameters": { - "type": "object" - } - }, - "required": [ - "name", - "description", - "parameters" - ], - "additionalProperties": false - } - }, - "safetySettings": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string" - }, - "threshold": { - "type": "string" - } - }, - "required": [ - "category", - "threshold" - ], - "additionalProperties": false - }, - "behavior": [ - "config" - ] - }, - "stopSequences": { - "type": "array", - "items": { - "type": "string" - }, - "behavior": [ - "config" - ] - }, - "responseMimeType": { - "type": "string", - "enum": [ - "text/plain", - "application/json" - ], - "behavior": [ - "config" - ] - }, - "retry": { - "anyOf": [ - { - "type": "number", - "behavior": [ - "config" - ] - }, - { - "type": "number" - } - ] - }, - "error": { - "anyOf": [ - { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - }, - { - "type": "object", - "properties": { - "error": { - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": [], - "additionalProperties": false - } - }, - "required": [], - "additionalProperties": false - } - ] - } - } - }, - "name": "count_retries", - "outputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "model", - "user", - "tool", - "$metadata" - ] - }, - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "inlineData": { - "type": "object", - "properties": { - "mimeType": { - "type": "string", - "enum": [ - "image/png", - "image/jpeg", - "image/heic", - "image/heif", - "image/webp" - ] - }, - "data": { - "type": "string" - } - }, - "required": [ - "mimeType", - "data" - ], - "additionalProperties": false - } - }, - "required": [ - "inlineData" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_call": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "function_call" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_response": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "response": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "name", - "response" - ], - "additionalProperties": false - } - }, - "required": [ - "function_response" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "role", - "parts" - ], - "additionalProperties": false - } - }, - "systemInstruction": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "inlineData": { - "type": "object", - "properties": { - "mimeType": { - "type": "string", - "enum": [ - "image/png", - "image/jpeg", - "image/heic", - "image/heif", - "image/webp" - ] - }, - "data": { - "type": "string" - } - }, - "required": [ - "mimeType", - "data" - ], - "additionalProperties": false - } - }, - "required": [ - "inlineData" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_call": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "function_call" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_response": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "response": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "name", - "response" - ], - "additionalProperties": false - } - }, - "required": [ - "function_response" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false - } - ] - }, - "text": { - "type": "string" - }, - "model": { - "type": "string" - }, - "tools": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "parameters": { - "type": "object" - } - }, - "required": [ - "name", - "description", - "parameters" - ], - "additionalProperties": false - } - }, - "safetySettings": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string" - }, - "threshold": { - "type": "string" - } - }, - "required": [ - "category", - "threshold" - ], - "additionalProperties": false - } - }, - "stopSequences": { - "type": "array", - "items": { - "type": "string" - } - }, - "responseMimeType": { - "type": "string", - "enum": [ - "text/plain", - "application/json" - ] - }, - "retry": { - "type": "number" - } - } - }, - "raw": true - }, - "metadata": { - "title": "Check Retry Count", - "description": "Making sure we can retry, if necessary." - } - }, - { - "id": "fetch-gemini-api", - "type": "fetch", - "configuration": { - "method": "POST" - }, - "metadata": { - "title": "Make API Call", - "description": "Calling Gemini API" - } - }, - { - "id": "format-response", - "type": "runJavascript", - "configuration": { - "code": "const format_response = ({ response }) => {\n const r = response;\n const context = r?.candidates?.[0].content;\n const firstPart = context?.parts?.[0];\n if (!firstPart) {\n return {\n $error: `No parts in response \"${JSON.stringify(response)}\" found`,\n };\n }\n if (\"text\" in firstPart) {\n return { text: firstPart.text, context };\n }\n else {\n return { context };\n }\n};", - "inputSchema": { - "type": "object", - "properties": { - "response": { - "type": "object", - "properties": { - "candidates": { - "type": "array", - "items": { - "type": "object", - "properties": { - "content": { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false - } - }, - "required": [ - "content" - ], - "additionalProperties": false - } - } - }, - "required": [ - "candidates" - ], - "additionalProperties": false - } - } - }, - "name": "format_response", - "outputSchema": { - "type": "object", - "properties": { - "text": { - "type": "string" - }, - "context": { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "functionCall": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "functionCall" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false - } - } - }, - "raw": true - }, - "metadata": { - "title": "Format Response", - "description": "Formatting Gemini API response" - } - }, - { - "id": "GEMINI_KEY-secret", - "type": "secrets", - "configuration": { - "keys": [ - "GEMINI_KEY" - ] - } - }, - { - "id": "make-body", - "type": "runJavascript", - "configuration": { - "code": "const make_body = ({ context, systemInstruction, responseMimeType, text, model, tools, safetySettings, stopSequences, }) => {\n let contents = context;\n const olderModel = model === \"gemini-pro\" || model === \"gemini-ultra\";\n const turn = { role: \"user\", parts: [{ text }] };\n if (!contents || contents.length === 0) {\n if (text) {\n contents = [turn];\n }\n else {\n throw new Error(\"Either `text` or `context` parameter is required\");\n }\n }\n else {\n // Replace the \"tool\" role with \"user\".\n contents = contents.map((item) => item.role === \"tool\" ? ((item.role = \"user\"), item) : item);\n const last = contents[contents.length - 1];\n if (last.role === \"model\") {\n contents.push(turn);\n }\n }\n // Filter out the special \"$metadata\" role.\n contents = contents.filter((item) => item.role !== \"$metadata\");\n const result = { contents };\n if (systemInstruction) {\n let parts;\n if (typeof systemInstruction === \"string\") {\n parts = [{ text: systemInstruction }];\n }\n else {\n parts = systemInstruction.parts;\n if (!parts) {\n throw new Error(`Malformed system instruction: ${JSON.stringify(systemInstruction)}`);\n }\n }\n if (olderModel) {\n contents[contents.length - 1].parts.unshift(...parts);\n }\n else {\n result.systemInstruction = { parts };\n }\n }\n if (safetySettings && !Object.keys(safetySettings).length) {\n result.safetySettings = [\n {\n category: \"HARM_CATEGORY_SEXUALLY_EXPLICIT\",\n threshold: \"BLOCK_NONE\",\n },\n {\n category: \"HARM_CATEGORY_HARASSMENT\",\n threshold: \"BLOCK_NONE\",\n },\n {\n category: \"HARM_CATEGORY_DANGEROUS_CONTENT\",\n threshold: \"BLOCK_NONE\",\n },\n ];\n }\n else {\n result.safetySettings = safetySettings;\n }\n const generationConfig = {};\n if (stopSequences && stopSequences.length > 0) {\n generationConfig.stopSequences = stopSequences;\n }\n if (responseMimeType) {\n generationConfig.responseMimeType = responseMimeType;\n }\n if (Object.keys(generationConfig).length > 0) {\n result.generationConfig = generationConfig;\n }\n if (tools && tools.length > 0) {\n result.tools = { function_declarations: tools };\n }\n return { result };\n};", - "inputSchema": { - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "properties": { - "role": { - "type": "string", - "enum": [ - "model", - "user", - "tool", - "$metadata" - ] - }, - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "inlineData": { - "type": "object", - "properties": { - "mimeType": { - "type": "string", - "enum": [ - "image/png", - "image/jpeg", - "image/heic", - "image/heif", - "image/webp" - ] - }, - "data": { - "type": "string" - } - }, - "required": [ - "mimeType", - "data" - ], - "additionalProperties": false - } - }, - "required": [ - "inlineData" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_call": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "function_call" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_response": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "response": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "name", - "response" - ], - "additionalProperties": false - } - }, - "required": [ - "function_response" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "role", - "parts" - ], - "additionalProperties": false - } - }, - "systemInstruction": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "object", - "properties": { - "text": { - "type": "string" - } - }, - "required": [ - "text" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "inlineData": { - "type": "object", - "properties": { - "mimeType": { - "type": "string", - "enum": [ - "image/png", - "image/jpeg", - "image/heic", - "image/heif", - "image/webp" - ] - }, - "data": { - "type": "string" - } - }, - "required": [ - "mimeType", - "data" - ], - "additionalProperties": false - } - }, - "required": [ - "inlineData" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_call": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "args": { - "type": "object", - "properties": {}, - "required": [], - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "name", - "args" - ], - "additionalProperties": false - } - }, - "required": [ - "function_call" - ], - "additionalProperties": false - }, - { - "type": "object", - "properties": { - "function_response": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "response": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - }, - "required": [ - "name", - "response" - ], - "additionalProperties": false - } - }, - "required": [ - "function_response" - ], - "additionalProperties": false - } - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false - } - ] - }, - "text": { - "type": "string" - }, - "model": { - "type": "string" - }, - "tools": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "parameters": { - "type": "object" - } - }, - "required": [ - "name", - "description", - "parameters" - ], - "additionalProperties": false - } - }, - "safetySettings": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string" - }, - "threshold": { - "type": "string" - } - }, - "required": [ - "category", - "threshold" - ], - "additionalProperties": false - } - }, - "stopSequences": { - "type": "array", - "items": { - "type": "string" - } - }, - "responseMimeType": { - "type": "string", - "enum": [ - "text/plain", - "application/json" - ] - } - } - }, - "name": "make_body", - "outputSchema": { - "type": "object", - "properties": { - "result": { - "type": "object", - "properties": { - "contents": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - }, - "systemInstruction": { - "type": "object", - "properties": { - "parts": { - "type": "array", - "items": { - "type": [ - "array", - "boolean", - "null", - "number", - "object", - "string" - ] - } - } - }, - "required": [ - "parts" - ], - "additionalProperties": false - }, - "safetySettings": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string" - }, - "threshold": { - "type": "string" - } - }, - "required": [ - "category", - "threshold" - ], - "additionalProperties": false - } - }, - "generationConfig": { - "type": "object", - "properties": { - "stopSequences": { - "type": "array", - "items": { - "type": "string" - } - }, - "responseMimeType": { - "type": "string", - "enum": [ - "text/plain", - "application/json" - ] - } - }, - "required": [], - "additionalProperties": false - }, - "tools": { - "type": "object", - "properties": { - "function_declarations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "parameters": { - "type": "object" - } - }, - "required": [ - "name", - "description", - "parameters" - ], - "additionalProperties": false - } - } - }, - "required": [ - "function_declarations" - ], - "additionalProperties": false - } - }, - "required": [ - "contents" - ], - "additionalProperties": false - } - } - }, - "raw": true - }, - "metadata": { - "title": "Make Request Body" - } - }, - { - "id": "make-url", - "type": "urlTemplate", - "configuration": { - "template": "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}" - }, - "metadata": { - "title": "Make URL", - "description": "Creating the Gemini API URL" - } - } - ], - "metadata": { - "help": { - "url": "https://breadboard-ai.github.io/breadboard/docs/kits/gemini/#the-text-component" - } - } -} \ No newline at end of file diff --git a/packages/gemini-kit/package.json b/packages/gemini-kit/package.json deleted file mode 100644 index d527a1befc0..00000000000 --- a/packages/gemini-kit/package.json +++ /dev/null @@ -1,115 +0,0 @@ -{ - "name": "@google-labs/gemini-kit", - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "version": "0.8.0", - "description": "A Breadboard kit for using Gemini API", - "main": "./dist/src/index.js", - "exports": "./dist/src/index.js", - "types": "dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "dev": "wireit", - "test": "wireit", - "build": "wireit", - "lint": "wireit", - "generate:graphs": "wireit" - }, - "wireit": { - "dev": { - "command": "breadboard debug src/boards --watch -n", - "dependencies": [ - "build", - "../breadboard-cli:build" - ] - }, - "build": { - "dependencies": [ - "../breadboard:build", - "../core-kit:build", - "../template-kit:build", - "build:tsc" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "../breadboard:build:tsc", - "../core-kit:build:tsc", - "../template-kit:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/", - "!dist/**/*.min.js{,.map}" - ], - "clean": "if-file-deleted" - }, - "test": { - "command": "echo no tests" - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - }, - "generate:graphs": { - "command": "mkdir graphs && ls dist/src/boards/*.js | xargs -n1 -r -I{} ../breadboard-cli/dist/src/index.js make \"$PWD/{}\" -o \"$PWD/graphs/\" --format", - "dependencies": [ - "build:tsc", - "../breadboard-cli:build" - ], - "files": [], - "output": [ - "graphs/" - ] - } - }, - "repository": { - "directory": "packages/gemini-kit", - "type": "git", - "url": "https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src" - ], - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard#readme", - "devDependencies": { - "@google-labs/breadboard-cli": "^0.11.2", - "@google-labs/tsconfig": "^0.0.1", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "typescript": "^5.6.2" - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/template-kit": "^0.3.10" - } -} diff --git a/packages/gemini-kit/src/boards/gemini-generator.ts b/packages/gemini-kit/src/boards/gemini-generator.ts deleted file mode 100644 index 8e82b8a1977..00000000000 --- a/packages/gemini-kit/src/boards/gemini-generator.ts +++ /dev/null @@ -1,600 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - annotate, - anyOf, - array, - board, - constant, - converge, - enumeration, - input, - loopback, - object, - optional, - output, - unsafeCast, - unsafeType, - inputNode, - outputNode, -} from "@breadboard-ai/build"; -import { ConvertBreadboardType } from "@breadboard-ai/build/internal/type-system/type.js"; -import { Schema } from "@google-labs/breadboard"; -import { code, fetch, passthrough, secret } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; - -const textPartType = object({ text: "string" }); - -const imagePartType = object({ - inlineData: object({ - mimeType: enumeration( - "image/png", - "image/jpeg", - "image/heic", - "image/heif", - "image/webp" - ), - data: "string", - }), -}); - -const functionCallPartType = object({ - function_call: object({ - name: "string", - args: object({}, "string"), - }), -}); - -const functionResponsePartType = object({ - function_response: object({ - name: "string", - response: "unknown", - }), -}); - -const partType = anyOf( - textPartType, - imagePartType, - functionCallPartType, - functionResponsePartType -); - -const generateContentContentsType = object({ - role: enumeration("model", "user", "tool", "$metadata"), - parts: array(partType), -}); - -const functionDeclaration = object({ - name: "string", - description: "string", - parameters: unsafeType({ type: "object" }), -}); - -const systemInstruction = input({ - type: annotate(anyOf("string", object({ parts: array(partType) })), { - behavior: ["config"], - }), - title: "System Instruction", - description: - "Give the model additional context to understand the task, provide more customized responses, and adhere to specific guidelines over the full user interaction.", - default: "", -}); - -const text = input({ - type: "string", - title: "Text", - description: "The text to generate", - default: "", -}); - -const model = input({ - title: "Model", - description: "The model to use for generation", - type: annotate( - enumeration( - "gemini-1.5-flash-latest", - "gemini-1.5-pro-latest", - "gemini-1.5-pro-exp-0801", - "gemini-1.5-pro-exp-0827", - "gemini-1.5-flash-8b-exp-0827", - "gemini-1.5-flash-exp-0827" - ), - { - behavior: ["config"], - } - ), - examples: ["gemini-1.5-flash-latest"], - default: "gemini-1.5-flash-latest", -}); - -const responseMimeType = input({ - title: "Response MIME Type", - description: "Output response mimetype of the generated text.", - type: annotate(enumeration("text/plain", "application/json"), { - behavior: ["config"], - }), - examples: ["text/plain"], - default: "text/plain", -}); - -const tools = input({ - type: array(functionDeclaration), - title: "Tools", - description: "An array of functions to use for tool-calling", - default: [], -}); - -const context = input({ - type: array( - annotate(generateContentContentsType, { - behavior: ["llm-content"], - }) - ), - title: "Context", - description: "An array of messages to use as conversation context", - default: [], -}); - -const useStreaming = input({ - type: annotate("boolean", { - behavior: ["deprecated"], - }), - title: "Stream Output", - description: "Whether to stream the output", - default: false, -}); - -const retry = input({ - type: annotate("number", { - behavior: ["config"], - }), - title: "Retry Count", - description: "The number of times to retry the LLM call in case of failure", - default: 1, -}); - -const safetySettings = input({ - type: annotate( - array( - object({ - category: "string", - threshold: "string", - }) - ), - { behavior: ["config"] } - ), - title: "Safety Settings", - description: - "The safety settings object (see https://ai.google.dev/api/rest/v1beta/SafetySetting for more information)", - default: [], -}); - -const stopSequences = input({ - type: annotate(array("string"), { - behavior: ["config"], - }), - title: "Stop Sequences", - description: "An array of strings that will stop the output", - default: [], -}); - -const requestBodyType = object({ - contents: "unknown", - systemInstruction: optional( - object({ - parts: array("unknown"), - }) - ), - safetySettings: optional( - array( - object({ - category: "string", - threshold: "string", - }) - ) - ), - generationConfig: optional( - object({ - stopSequences: optional(array("string")), - responseMimeType: optional(enumeration("text/plain", "application/json")), - }) - ), - tools: optional( - object({ - function_declarations: array(functionDeclaration), - }) - ), -}); - -const { method, sseOption } = code( - { - $id: "choose-method", - useStreaming, - $metadata: { - title: "Choose Method", - description: "Choosing the right Gemini API method", - }, - }, - { - method: enumeration("streamGenerateContent", "generateContent"), - sseOption: "string", - }, - ({ useStreaming }) => { - const method = useStreaming ? "streamGenerateContent" : "generateContent"; - const sseOption = useStreaming ? "&alt=sse" : ""; - return { method, sseOption }; - } -).outputs; - -const makeUrl = urlTemplate({ - $id: "make-url", - $metadata: { - title: "Make URL", - description: "Creating the Gemini API URL", - }, - template: - "https://generativelanguage.googleapis.com/v1beta/models/{model}:{method}?key={GEMINI_KEY}{+sseOption}", - GEMINI_KEY: secret("GEMINI_KEY"), - model, - method, - sseOption, -}); - -const errorLoopback = loopback({ - type: object({ - error: optional( - object({ - message: optional("string"), - }) - ), - }), -}); - -const retryLoopback = loopback({ type: "number" }); - -export type ErrorResponse = { - error?: { - message?: string; - code?: number; - }; -}; - -const countRetries = code( - { - $id: "count-retries", - $metadata: { - title: "Check Retry Count", - description: "Making sure we can retry, if necessary.", - }, - context: constant(context), - systemInstruction: constant(systemInstruction), - text: constant(text), - model: constant(model), - tools: constant(tools), - safetySettings: constant(safetySettings), - stopSequences: constant(stopSequences), - responseMimeType: constant(responseMimeType), - retry: converge(retry, retryLoopback), - error: converge({} as { error?: { message?: string } }, errorLoopback), - }, - { - // TODO(aomarks) A better way to generate these types. - context: array(generateContentContentsType), - systemInstruction: anyOf("string", object({ parts: array(partType) })), - text: "string", - model: "string", - tools: array(functionDeclaration), - safetySettings: array(object({ category: "string", threshold: "string" })), - stopSequences: array("string"), - responseMimeType: enumeration("text/plain", "application/json"), - retry: "number", - }, - ({ retry, error, ...rest }) => { - retry = retry || 0; - let errorResponse: ErrorResponse = {}; - try { - errorResponse = JSON.parse(error?.error?.message || "null"); - } catch (e) { - // Ignore the error - } - const errorCode = errorResponse?.error?.code; - if (errorCode) { - // Retry won't help with 404, 429 or 400, because these are either the - // caller's problem or in case of 429, retries are actually doing more harm - // than good. - const retryWontHelp = - errorCode == 400 || errorCode == 429 || errorCode == 404; - if (retryWontHelp) { - // TODO(aomarks) We don't have `code` in the general $error type, and we - // probably shouldn't since there are all kind of possible error shapes. - // There should probably be a way to set the schema for $error to any - // sub-type of the general one on a node-by-node basis. For now we just - // cast to pretend `code` isn't there. - return { $error: error as { message: string } }; - } - // The "-1" value is something that responseFormatter sends when empty - // response is encountered. - if (errorCode == -1) { - return { $error: error as { message: string } }; - } - } - if (retry < 0) { - return { - $error: - "Exceeded retry count, was unable to produce a useful response from the Gemini API.", - }; - } - retry = retry - 1; - return { ...rest, retry }; - } -); - -const body = code( - { - $id: "make-body", - $metadata: { title: "Make Request Body" }, - context: countRetries.outputs.context, - systemInstruction: countRetries.outputs.systemInstruction, - text: countRetries.outputs.text, - model: countRetries.outputs.model, - tools: countRetries.outputs.tools, - safetySettings: countRetries.outputs.safetySettings, - stopSequences: countRetries.outputs.stopSequences, - responseMimeType: countRetries.outputs.responseMimeType, - }, - { result: requestBodyType }, - ({ - context, - systemInstruction, - responseMimeType, - text, - model, - tools, - safetySettings, - stopSequences, - }) => { - let contents = context; - const olderModel = model === "gemini-pro" || model === "gemini-ultra"; - const turn = { role: "user" as const, parts: [{ text }] }; - if (!contents || contents.length === 0) { - if (text) { - contents = [turn]; - } else { - throw new Error("Either `text` or `context` parameter is required"); - } - } else { - // Replace the "tool" role with "user". - contents = contents.map((item) => - item.role === "tool" ? ((item.role = "user"), item) : item - ); - const last = contents[contents.length - 1]; - if (last.role === "model") { - contents.push(turn); - } - } - // Filter out the special "$metadata" role. - contents = contents.filter((item) => item.role !== "$metadata"); - const result: ConvertBreadboardType = { contents }; - if (systemInstruction) { - let parts; - if (typeof systemInstruction === "string") { - parts = [{ text: systemInstruction }]; - } else { - parts = systemInstruction.parts; - if (!parts || parts.length === 0) { - throw new Error( - `Malformed system instruction: ${JSON.stringify(systemInstruction)}` - ); - } - } - if (olderModel) { - contents[contents.length - 1].parts.unshift(...parts); - } else { - result.systemInstruction = { parts }; - } - } - if (safetySettings && !Object.keys(safetySettings).length) { - result.safetySettings = [ - { - category: "HARM_CATEGORY_SEXUALLY_EXPLICIT", - threshold: "BLOCK_NONE", - }, - { - category: "HARM_CATEGORY_HARASSMENT", - threshold: "BLOCK_NONE", - }, - { - category: "HARM_CATEGORY_DANGEROUS_CONTENT", - threshold: "BLOCK_NONE", - }, - ]; - } else { - result.safetySettings = safetySettings; - } - const generationConfig: { - stopSequences?: string[]; - responseMimeType?: "text/plain" | "application/json"; - } = {}; - if (stopSequences && stopSequences.length > 0) { - generationConfig.stopSequences = stopSequences; - } - if (responseMimeType) { - generationConfig.responseMimeType = responseMimeType; - } - if (Object.keys(generationConfig).length > 0) { - result.generationConfig = generationConfig; - } - if (tools && tools.length > 0) { - result.tools = { function_declarations: tools }; - } - return { result }; - } -).outputs.result; - -const responseContentType = object({ - parts: array( - anyOf( - object({ - text: "string", - }), - object({ - functionCall: "unknown", - }) - ) - ), -}); - -const responseType = object({ - candidates: array( - object({ - content: responseContentType, - }) - ), -}); - -const fetchResult = fetch({ - $id: "fetch-gemini-api", - $metadata: { title: "Make API Call", description: "Calling Gemini API" }, - method: "POST", - stream: constant(useStreaming), - url: constant(makeUrl), - body, -}); - -const response = unsafeCast(fetchResult.outputs.response, responseType); - -const formattedResponse = code( - { - $id: "format-response", - $metadata: { - title: "Format Response", - description: "Formatting Gemini API response", - }, - response, - }, - { - text: { - type: "string", - optional: true, - }, - context: responseContentType, - }, - ({ response }) => { - const r = response; - const context = r?.candidates?.[0].content; - const firstPart = context?.parts?.[0]; - if (!firstPart) { - return { - $error: `No parts in response "${JSON.stringify(response)}" found`, - }; - } - if ("text" in firstPart) { - return { text: firstPart.text, context }; - } else { - return { context }; - } - } -); - -const errorCollector = passthrough({ - $id: "collect-errors", - $metadata: { - title: "Collect Errors", - description: "Collecting the error from Gemini API", - }, - error: converge(fetchResult.outputs.$error, formattedResponse.outputs.$error), - retry: countRetries.outputs.retry, -}); - -retryLoopback.resolve(errorCollector.outputs.retry); -errorLoopback.resolve(errorCollector.outputs.error); - -// const streamTransform = nursery.transformStream({ -// $metadata: { -// title: "Transform Stream", -// description: "Transforming the API output stream to be consumable", -// }, -// board: board(() => { -// const transformChunk = json.jsonata({ -// $id: "transformChunk", -// expression: -// "candidates[0].content.parts.text ? $join(candidates[0].content.parts.text) : ''", -// json: base.input({}).chunk as V, -// }); -// return base.output({ chunk: transformChunk.result }); -// }), -// stream: fetch, -// }); - -// return base.output({ -// $metadata: { title: "Stream Output", description: "Outputting a stream" }, -// schema: streamOutputSchema, -// stream: streamTransform, -// }); -// }).serialize(metadata); - -export default board({ - title: "Gemini Generator", - description: "Generates text using the Gemini API.", - metadata: { - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/gemini/#the-text-component", - }, - }, - version: "0.1.0", - inputs: inputNode( - { - systemInstruction, - text, - model, - responseMimeType, - tools, - context, - useStreaming, - retry, - safetySettings, - stopSequences, - }, - { - id: "inputs", - title: "Input Parameters", - description: "Collecting input parameters", - } - ), - outputs: [ - outputNode( - { - context: output(formattedResponse.outputs.context, { - title: "Context", - description: "The conversation context", - }), - text: output(formattedResponse.outputs.text, { - title: "Text", - description: "The generated text", - }), - }, - { - id: "content-output", - title: "Content Output", - description: "Outputting content", - } - ), - outputNode( - { - context: output(formattedResponse.outputs.context, { - title: "Context", - description: "The conversation context", - }), - }, - { - id: "tool-call-output", - title: "Tool Call Output", - description: "Outputting a tool call", - } - ), - ], -}); diff --git a/packages/gemini-kit/src/boards/nano-generator.ts b/packages/gemini-kit/src/boards/nano-generator.ts deleted file mode 100644 index fced380f713..00000000000 --- a/packages/gemini-kit/src/boards/nano-generator.ts +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { board, input, output } from "@breadboard-ai/build"; -import { code } from "@google-labs/core-kit"; - -declare global { - // eslint-disable-next-line no-var - var ai: { - createTextSession: () => Promise<{ - prompt: (text: string) => Promise; - }>; - canCreateTextSession: () => Promise; - }; -} - -const prompt = input({ - title: "Prompt", - description: "The prompt to generate text from", -}); - -const { text } = code( - { - $metadata: { - title: "Call Prompt API", - description: "Invoking the Prompt API to generate text from a prompt", - }, - prompt, - }, - { text: "string" }, - async ({ prompt }) => { - const ERROR_MESSAGE = - "Prompt API is not available. For more information, see https://developer.chrome.com/docs/ai/built-in."; - - const ai = globalThis.ai; - if (!ai) { - throw new Error(ERROR_MESSAGE); - } - const canAI = await ai.canCreateTextSession(); - if (!canAI) { - throw new Error(ERROR_MESSAGE); - } - const session = await ai.createTextSession(); - const text = (await session.prompt(prompt)) as string; - return { text }; - } -).outputs; - -export default board({ - title: "Gemini Nano (Preview)", - description: "Generates text with the on-device Gemini Nano model", - metadata: { - icon: "nano", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/gemini/#the-nano-component", - }, - }, - inputs: { prompt }, - outputs: { - text: output(text, { - title: "Text", - description: "The generated text", - }), - }, -}); diff --git a/packages/gemini-kit/src/index.ts b/packages/gemini-kit/src/index.ts deleted file mode 100644 index 37c7c01d02a..00000000000 --- a/packages/gemini-kit/src/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { kit } from "@breadboard-ai/build"; -import text from "./boards/gemini-generator.js"; -import nano from "./boards/nano-generator.js"; - -const geminiKit = await kit({ - title: "Gemini Kit", - description: "Nodes for calling Google Gemini APIs", - version: "0.1.0", - url: "npm:@google-labs/gemini-kit", - components: { text, nano }, -}); - -export default geminiKit; -export const gemini = await geminiKit.legacy(); -export { text as geminiText }; diff --git a/packages/gemini-kit/tsconfig.json b/packages/gemini-kit/tsconfig.json deleted file mode 100644 index 1ff943cd641..00000000000 --- a/packages/gemini-kit/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "outDir": "./dist" - }, - "include": ["src/**/*", "tests/**/*"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/google-drive-kit/.eslintrc b/packages/google-drive-kit/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/google-drive-kit/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/google-drive-kit/.gitignore b/packages/google-drive-kit/.gitignore deleted file mode 100644 index 4a87a3f73c7..00000000000 --- a/packages/google-drive-kit/.gitignore +++ /dev/null @@ -1 +0,0 @@ -graphs/ \ No newline at end of file diff --git a/packages/google-drive-kit/CHANGELOG.md b/packages/google-drive-kit/CHANGELOG.md deleted file mode 100644 index 41fc74996de..00000000000 --- a/packages/google-drive-kit/CHANGELOG.md +++ /dev/null @@ -1,168 +0,0 @@ -# @breadboard-ai/google-drive-kit - -## 0.2.4 - -### Patch Changes - -- 54c8197: Make build API kit function async -- Updated dependencies [49e2740] -- Updated dependencies [54c8197] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [2fa05f0] -- Updated dependencies [f61ccf3] -- Updated dependencies [f71bcfb] -- Updated dependencies [3188607] -- Updated dependencies [88298d5] -- Updated dependencies [b673bfa] -- Updated dependencies [8540b93] -- Updated dependencies [feeed7a] -- Updated dependencies [8330f0c] -- Updated dependencies [1423647] -- Updated dependencies [9783ba8] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [91fe8bb] -- Updated dependencies [100fc95] -- Updated dependencies [4423c35] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [5834c81] -- Updated dependencies [0ef793f] -- Updated dependencies [9c04caa] - - @breadboard-ai/build@0.10.0 - - @google-labs/core-kit@0.15.0 - - @google-labs/template-kit@0.3.10 - -## 0.2.3 - -### Patch Changes - -- a940b87: Switch to new style of declaring components in kits. -- Updated dependencies [cc5f4b6] -- Updated dependencies [a4301e6] -- Updated dependencies [a940b87] -- Updated dependencies [374ea85] -- Updated dependencies [f93ec06] -- Updated dependencies [cc5f4b6] -- Updated dependencies [398bf4f] -- Updated dependencies [7de241c] -- Updated dependencies [ee1f9ca] - - @breadboard-ai/build@0.9.0 - - @google-labs/core-kit@0.14.0 - - @google-labs/template-kit@0.3.8 - -## 0.2.2 - -### Patch Changes - -- Updated dependencies [00cc2c5] -- Updated dependencies [d88c37b] -- Updated dependencies [3a5ced1] - - @google-labs/core-kit@0.13.0 - - @breadboard-ai/build@0.8.1 - - @google-labs/template-kit@0.3.7 - -## 0.2.1 - -### Patch Changes - -- cb0f513: Convert google-drive to use new kit function. -- 38e3232: Annotate file ID/query inputs with new behaviors so that the dedicated input components will be used for them. -- 9a2ffab: Unpin @breadboard-ai/build dependency from being overly constrained -- 0a846ff: Switch from google-drive connection id to google-drive-limited, which requests access only to shared files, not all files. -- Updated dependencies [ad8aa22] -- Updated dependencies [6d2939e] -- Updated dependencies [15b6171] -- Updated dependencies [5c5b665] -- Updated dependencies [f78ec0a] -- Updated dependencies [a0852df] -- Updated dependencies [7298a47] -- Updated dependencies [ea7e2a1] -- Updated dependencies [8edcbc0] -- Updated dependencies [9a2ffab] -- Updated dependencies [b99472b] -- Updated dependencies [4bfaec5] -- Updated dependencies [2312443] -- Updated dependencies [b76f9a1] -- Updated dependencies [15ae381] - - @breadboard-ai/build@0.8.0 - - @google-labs/core-kit@0.12.0 - - @google-labs/template-kit@0.3.6 - -## 0.2.0 - -### Minor Changes - -- f2d9839: Move components into component folder. Fix some names & descriptions.. - -### Patch Changes - -- 5f6432b: Internal type-safety improvement to list-files -- Updated dependencies [f4d2416] -- Updated dependencies [bc94299] -- Updated dependencies [166f290] -- Updated dependencies [da43bb5] -- Updated dependencies [5cf08f1] -- Updated dependencies [9d93cf8] -- Updated dependencies [9d93cf8] -- Updated dependencies [9d93cf8] -- Updated dependencies [26e1099] -- Updated dependencies [a9def5c] - - @google-labs/core-kit@0.11.0 - - @breadboard-ai/build@0.7.1 - - @google-labs/template-kit@0.3.5 - -## 0.1.3 - -### Patch Changes - -- 29774aa: Update dependency package versions. -- Updated dependencies [29774aa] - - @google-labs/template-kit@0.3.4 - - @google-labs/core-kit@0.10.1 - -## 0.1.2 - -### Patch Changes - -- 71d5696: Mark google-drive-kit as public. - -## 0.1.1 - -### Patch Changes - -- Updated dependencies [c27c176] -- Updated dependencies [4e66406] -- Updated dependencies [417323c] -- Updated dependencies [85bbc00] -- Updated dependencies [00825d5] -- Updated dependencies [3d7b4a7] -- Updated dependencies [4db3ab7] -- Updated dependencies [d9b76bd] -- Updated dependencies [14853d5] -- Updated dependencies [5a0afe4] -- Updated dependencies [6fdd89e] -- Updated dependencies [c82138d] -- Updated dependencies [cd73b17] -- Updated dependencies [3e10f0f] -- Updated dependencies [0e54e55] -- Updated dependencies [c53ca01] -- Updated dependencies [6ada218] -- Updated dependencies [0e76614] -- Updated dependencies [2ace620] -- Updated dependencies [c5f8e4f] -- Updated dependencies [fcef799] -- Updated dependencies [26556b6] -- Updated dependencies [5f09b1d] -- Updated dependencies [b75a43e] -- Updated dependencies [6fdd89e] -- Updated dependencies [9b1513a] -- Updated dependencies [510e198] -- Updated dependencies [9491266] -- Updated dependencies [06c3f57] - - @google-labs/core-kit@0.10.0 - - @breadboard-ai/build@0.7.0 - - @google-labs/template-kit@0.3.3 diff --git a/packages/google-drive-kit/README.md b/packages/google-drive-kit/README.md deleted file mode 100644 index 78ce41f0e06..00000000000 --- a/packages/google-drive-kit/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Breadboard Google Drive Kit - -[![Published on npm](https://img.shields.io/npm/v/@breadboard-ai/google-drive-kit.svg?logo=npm)](https://www.npmjs.com/package/@breadboard-ai/google-drive-kit) - -A collection of components that are useful for working with Google Drive. diff --git a/packages/google-drive-kit/package.json b/packages/google-drive-kit/package.json deleted file mode 100644 index 377c67eb88b..00000000000 --- a/packages/google-drive-kit/package.json +++ /dev/null @@ -1,145 +0,0 @@ -{ - "name": "@breadboard-ai/google-drive-kit", - "version": "0.2.4", - "description": "Nodes for reading & writing to files in Google Drive, including Docs and Sheets", - "license": "Apache-2.0", - "author": "Google LLC", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/google-drive-kit#readme", - "repository": { - "directory": "packages/google-drive-kit", - "type": "git", - "url": "git+https://github.com/breadboard-ai/google-drive-kit.git" - }, - "type": "module", - "main": "dist/index.js", - "typings": "dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "./index.js": { - "types": null, - "default": null - }, - "./internal/*.js": { - "types": "./dist/internal/*.d.ts", - "default": null - }, - "./*.js": { - "types": "./dist/*.d.ts", - "default": "./dist/*.js" - } - }, - "files": [ - "dist/**/*.{js,js.map,d.ts}", - "!dist/test/", - "CHANGELOG.md" - ], - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "build:tsc": "wireit", - "test": "wireit", - "test:only": "wireit", - "coverage": "wireit", - "lint": "wireit", - "test-and-lint": "wireit", - "dev": "npm run test-and-lint --watch", - "generate:graphs": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "build:tsc", - "../build:build", - "../core-kit:build", - "../template-kit:build" - ] - }, - "build:tsc": { - "command": "tsc --pretty", - "dependencies": [ - "../build:build:tsc", - "../core-kit:build:tsc", - "../template-kit:build:tsc" - ], - "files": [ - "src/", - "tsconfig.json", - "package.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "test": { - "command": "node --test --test-reporter spec dist/test/*_test.js", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "test:only": { - "command": "node --test --test-only --enable-source-maps --test-reporter spec dist/test/*_test.js", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "coverage": { - "command": "node --test --enable-source-maps --experimental-test-coverage --test-reporter lcov --test-reporter-destination=lcov.info dist/test/*_test.js", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [ - "lcov.info" - ] - }, - "lint": { - "command": "eslint src/ --ext .ts", - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - }, - "test-and-lint": { - "dependencies": [ - "test", - "lint" - ] - }, - "generate:graphs": { - "command": "mkdir graphs && ls dist/components/*.js | xargs -n1 -r -I{} ../breadboard-cli/dist/src/index.js make \"$PWD/{}\" -o \"$PWD/graphs/\" --format", - "dependencies": [ - "build:tsc", - "../breadboard-cli:build:tsc" - ], - "files": [], - "output": [ - "graphs/" - ] - } - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/template-kit": "^0.3.10" - }, - "devDependencies": { - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" - } -} diff --git a/packages/google-drive-kit/src/components/export-file.ts b/packages/google-drive-kit/src/components/export-file.ts deleted file mode 100644 index 0a00c5fd586..00000000000 --- a/packages/google-drive-kit/src/components/export-file.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { annotate, board, input, output } from "@breadboard-ai/build"; -import { fetch } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; -import { headers } from "../internal/headers.js"; - -const fileId = input({ - title: "File ID", - description: `The ID of the Google Drive file. -See https://developers.google.com/drive/api/reference/rest/v3/files/export#body.PATH_PARAMETERS.file_id`, - type: annotate("string", { behavior: ["google-drive-file-id"] }), -}); - -const mimeType = input({ - title: "MIME Type", - description: `The MIME type of the format requested for this export. -See https://developers.google.com/drive/api/reference/rest/v3/files/export#body.QUERY_PARAMETERS.mime_type`, -}); - -const { url } = urlTemplate({ - // https://developers.google.com/drive/api/reference/rest/v3/files/export - template: - "https://www.googleapis.com/drive/v3/files/{fileId}/export{?mimeType}", - fileId, - mimeType, -}).outputs; - -const content = fetch({ url, headers }).outputs.response; - -export const exportFile = board({ - id: "exportFile", - metadata: { - title: "Export File", - description: - "Export a Google Workspace document to the requested MIME type.", - icon: "google-drive", - }, - inputs: { fileId, mimeType }, - outputs: { - content: output(content, { - title: "Content", - description: `The content of the file -See https://developers.google.com/drive/api/reference/rest/v3/files/export#response-body`, - }), - }, -}); - -export default exportFile; diff --git a/packages/google-drive-kit/src/components/get-file-content.ts b/packages/google-drive-kit/src/components/get-file-content.ts deleted file mode 100644 index 3f67ebdbc7d..00000000000 --- a/packages/google-drive-kit/src/components/get-file-content.ts +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { annotate, board, input, output } from "@breadboard-ai/build"; -import { fetch } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; -import { headers } from "../internal/headers.js"; - -const fileId = input({ - title: "File ID", - description: `The ID of the file. -See https://developers.google.com/drive/api/reference/rest/v3/files/get#body.PATH_PARAMETERS.file_id`, - type: annotate("string", { behavior: ["google-drive-file-id"] }), -}); - -const url = urlTemplate({ - // https://developers.google.com/drive/api/reference/rest/v3/files/get - template: "https://www.googleapis.com/drive/v3/files/{fileId}?alt=media", - fileId, -}); - -const response = fetch({ url, headers }); - -export const getFileContent = board({ - id: "getFileContent", - metadata: { - title: "Get File Content", - description: "Get the content of a file in Google Drive", - icon: "google-drive", - }, - inputs: { fileId }, - outputs: { - content: output(response, { - title: "Content", - description: `The content of the file`, - }), - }, -}); - -export default getFileContent; diff --git a/packages/google-drive-kit/src/components/list-files.ts b/packages/google-drive-kit/src/components/list-files.ts deleted file mode 100644 index a97511ea188..00000000000 --- a/packages/google-drive-kit/src/components/list-files.ts +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - annotate, - array, - board, - enumeration, - input, - object, - optional, - optionalEdge, - output, -} from "@breadboard-ai/build"; -import { cast, fetch, unnest } from "@google-labs/core-kit"; -import { urlTemplate } from "@google-labs/template-kit"; -import { headers } from "../internal/headers.js"; -import { fileType } from "../types.js"; - -const fileListType = object({ - kind: enumeration("drive#fileList"), - nextPageToken: optional("string"), - incompleteSearch: "boolean", - files: array(fileType), -}); - -const query = input({ - title: "Query", - description: `A Google Drive search query. -See https://developers.google.com/drive/api/guides/search-files for details.`, - type: annotate("string", { behavior: ["google-drive-query"] }), - examples: [ - "'' in parents", - "name = 'hello'", - "fullText contains 'hello'", - "mimeType = 'application/vnd.google-apps.folder'", - "sharedWithMe and name contains 'hello'", - ], -}); - -const url = urlTemplate({ - // https://developers.google.com/drive/api/reference/rest/v3/files/list - template: "https://www.googleapis.com/drive/v3/files?q={query}", - query, -}); - -const rawResponse = fetch({ url, headers }); -const response = cast(rawResponse, fileListType); -const { files, incompleteSearch, nextPageToken } = unnest(response); - -export const listFiles = board({ - id: "listFiles", - metadata: { - title: "List Files", - description: - "List files in Google Drive.\n\nSee https://developers.google.com/drive/api/guides/search-files for more details.", - icon: "google-drive", - }, - inputs: { query }, - outputs: { - files: output(files, { - title: "Files", - description: `The list of files. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.\n\nSee https://developers.google.com/drive/api/reference/rest/v3/files/list#body.FileList.FIELDS.files`, - }), - incompleteSearch: output(incompleteSearch, { - title: "Incomplete Search", - description: `Whether the search process was incomplete. If true, then some search results might be missing, since all documents were not searched. This can occur when searching multiple drives with the 'allDrives' corpora, but all corpora couldn't be searched. When this happens, it's suggested that clients narrow their query by choosing a different corpus such as 'user' or 'drive'.\n\nSee https://developers.google.com/drive/api/reference/rest/v3/files/list#body.FileList.FIELDS.incomplete_search`, - }), - nextPageToken: output(optionalEdge(nextPageToken), { - title: "Next Page Token", - description: `The page token for the next page of files. This will be absent if the end of the files list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.\n\nSee https://developers.google.com/drive/api/reference/rest/v3/files/list#body.FileList.FIELDS.next_page_token`, - }), - }, -}); - -export default listFiles; diff --git a/packages/google-drive-kit/src/index.ts b/packages/google-drive-kit/src/index.ts deleted file mode 100644 index 9f472a3ec07..00000000000 --- a/packages/google-drive-kit/src/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { kit } from "@breadboard-ai/build"; -import exportFile from "./components/export-file.js"; -import getFileContent from "./components/get-file-content.js"; -import listFiles from "./components/list-files.js"; - -export default await kit({ - title: "Google Drive Kit", - url: "npm:@breadboard-ai/google-drive-kit", - description: - "Nodes for reading & writing to files in Google Drive, including Docs and Sheets", - version: "0.0.1", - components: { getFileContent, listFiles, exportFile }, -}); diff --git a/packages/google-drive-kit/src/internal/headers.ts b/packages/google-drive-kit/src/internal/headers.ts deleted file mode 100644 index 937c791c99c..00000000000 --- a/packages/google-drive-kit/src/internal/headers.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { object } from "@breadboard-ai/build"; -import { code, secret } from "@google-labs/core-kit"; - -export const { headers } = code( - { token: secret("connection:google-drive-limited") }, - { headers: object({}, "string") }, - ({ token }) => ({ - headers: { - Authorization: `Bearer ${token}`, - }, - }) -).outputs; diff --git a/packages/google-drive-kit/src/test/export-file_test.ts b/packages/google-drive-kit/src/test/export-file_test.ts deleted file mode 100644 index df7b72205a7..00000000000 --- a/packages/google-drive-kit/src/test/export-file_test.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -// No test yet :( diff --git a/packages/google-drive-kit/src/types.ts b/packages/google-drive-kit/src/types.ts deleted file mode 100644 index 96ce32b6c2c..00000000000 --- a/packages/google-drive-kit/src/types.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { enumeration, object, optional } from "@breadboard-ai/build"; - -/** - * A Breadboard Type Expression corresponding to - * https://developers.google.com/drive/api/reference/rest/v3/files#File - */ -export const fileType = object({ - kind: enumeration("drive#file"), - mimeType: "string", - id: "string", - name: "string", - resourceKey: optional("string"), -}); diff --git a/packages/google-drive-kit/tsconfig.json b/packages/google-drive-kit/tsconfig.json deleted file mode 100644 index 4c0109444dd..00000000000 --- a/packages/google-drive-kit/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/.tsbuildinfo", - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "types": ["node"], - "lib": ["ES2022", "DOM"], - "incremental": true, - "declaration": true, - "sourceMap": true, - "inlineSources": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "noImplicitOverride": true, - "noUncheckedIndexedAccess": true, - "verbatimModuleSyntax": true, - "useUnknownInCatchVariables": true - }, - "include": ["src/**/*.ts"], - "exclude": [] -} diff --git a/packages/idb-board-server/.eslintrc b/packages/idb-board-server/.eslintrc deleted file mode 100644 index f72cccfe73a..00000000000 --- a/packages/idb-board-server/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"] - } -} diff --git a/packages/idb-board-server/.gitignore b/packages/idb-board-server/.gitignore deleted file mode 100644 index c819d9232a7..00000000000 --- a/packages/idb-board-server/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# pyodide assets that we copy into public/. We don't want to check these in -# because they come from NPM. -public/pyodide* -public/python* \ No newline at end of file diff --git a/packages/idb-board-server/CHANGELOG.md b/packages/idb-board-server/CHANGELOG.md deleted file mode 100644 index c87c33fe0df..00000000000 --- a/packages/idb-board-server/CHANGELOG.md +++ /dev/null @@ -1,92 +0,0 @@ -# @breadboard-ai/idb-board-server - -## 1.17.0 - -### Minor Changes - -- 157c31e: Implement remote board server -- d9fd0ab: [project-store] -> [idb-board-server] -- 60349b8: Add board server management and remote board server packages - -### Patch Changes - -- 9797718: Auto-migrate IDB `GraphProvider` boards -- Updated dependencies [49e2740] -- Updated dependencies [323216f] -- Updated dependencies [54c8197] -- Updated dependencies [f94f498] -- Updated dependencies [703f17d] -- Updated dependencies [8d06f3c] -- Updated dependencies [6136d87] -- Updated dependencies [0273985] -- Updated dependencies [f5d3111] -- Updated dependencies [cb8c99a] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [8f9fddf] -- Updated dependencies [2fa05f0] -- Updated dependencies [4e0a4f6] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [f71bcfb] -- Updated dependencies [a104fa7] -- Updated dependencies [f0b5ccc] -- Updated dependencies [8a1b8c4] -- Updated dependencies [3188607] -- Updated dependencies [58d2e8c] -- Updated dependencies [9797718] -- Updated dependencies [679719b] -- Updated dependencies [88298d5] -- Updated dependencies [b673bfa] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [feeed7a] -- Updated dependencies [4cc71ee] -- Updated dependencies [8330f0c] -- Updated dependencies [9b62fc2] -- Updated dependencies [a039d2e] -- Updated dependencies [e63b5dd] -- Updated dependencies [1423647] -- Updated dependencies [74d50d4] -- Updated dependencies [9783ba8] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [9ce8ad3] -- Updated dependencies [7fdf9c2] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [91fe8bb] -- Updated dependencies [e38bf19] -- Updated dependencies [100fc95] -- Updated dependencies [4423c35] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [78d6394] -- Updated dependencies [5834c81] -- Updated dependencies [d7606d3] -- Updated dependencies [0ef793f] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] -- Updated dependencies [9c04caa] -- Updated dependencies [e026112] -- Updated dependencies [94759f7] -- Updated dependencies [281ab28] -- Updated dependencies [e74ee2f] -- Updated dependencies [5fc6e8b] - - @breadboard-ai/build@0.10.0 - - @google-labs/gemini-kit@0.8.0 - - @google-labs/core-kit@0.15.0 - - @google-labs/json-kit@0.3.8 - - @google-labs/agent-kit@0.12.0 - - @google-labs/breadboard@0.27.0 - - @google-labs/breadboard-schema@1.8.0 - - @google-labs/template-kit@0.3.10 - - @google-labs/node-nursery-web@1.3.2 - - @breadboard-ai/data-store@0.2.3 - - @google-labs/palm-kit@0.1.4 diff --git a/packages/idb-board-server/README.md b/packages/idb-board-server/README.md deleted file mode 100644 index 4da90d16355..00000000000 --- a/packages/idb-board-server/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# IDB Board Server - -A Board Server implementation backed by IDB. diff --git a/packages/idb-board-server/package.json b/packages/idb-board-server/package.json deleted file mode 100644 index 96e64c26f52..00000000000 --- a/packages/idb-board-server/package.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "name": "@breadboard-ai/idb-board-server", - "version": "1.17.0", - "description": "IDB Board Server for Breadboard", - "main": "./dist/index.js", - "exports": { - ".": { - "default": "./dist/index.js", - "types": "./dist/index.d.ts" - } - }, - "types": "dist/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "build:tsc": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "../breadboard:build", - "../build:build", - "../data-store:build", - "../schema:build", - "../agent-kit:build", - "../core-kit:build", - "../google-drive-kit:build", - "../json-kit:build", - "../template-kit:build", - "../palm-kit:build", - "build:tsc" - ] - }, - "typescript-files-and-deps": { - "dependencies": [ - "../breadboard:build:tsc", - "../build:build:tsc", - "../data-store:build:tsc", - "../schema:build:tsc", - "../agent-kit:build:tsc", - "../core-kit:build:tsc", - "../google-drive-kit:build:tsc", - "../json-kit:build:tsc", - "../template-kit:build:tsc", - "../palm-kit:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "typescript-files-and-deps" - ], - "files": [], - "output": [ - "dist/", - "!dist/**/*.min.js{,.map}" - ], - "clean": "if-file-deleted" - } - }, - "repository": { - "directory": "packages/idb-board-server", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/" - ], - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/idb-board-server#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@google-labs/tsconfig": "^0.0.1", - "@types/markdown-it": "^14.1.2", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "dotenv": "^16.4.5", - "tsx": "^4.19.1", - "typescript": "^5.6.2", - "vite": "^5.4.8", - "vite-plugin-full-reload": "^1.2.0", - "vite-plugin-watch-and-run": "^1.7.0", - "vitest": "^2.1.1" - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/data-store": "^0.2.3", - "@google-labs/agent-kit": "^0.12.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/breadboard-schema": "^1.8.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/gemini-kit": "^0.8.0", - "@google-labs/json-kit": "^0.3.8", - "@google-labs/node-nursery-web": "^1.3.2", - "@google-labs/palm-kit": "^0.1.4", - "@google-labs/template-kit": "^0.3.10", - "idb": "^8.0.0", - "idb-keyval": "^6.2.1" - } -} diff --git a/packages/idb-board-server/src/idb-board-server.ts b/packages/idb-board-server/src/idb-board-server.ts deleted file mode 100644 index b020490f172..00000000000 --- a/packages/idb-board-server/src/idb-board-server.ts +++ /dev/null @@ -1,464 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - BoardServer, - BoardServerProject, - BoardServerCapabilities, - BoardServerConfiguration, - BoardServerExtension, - ChangeNotificationCallback, - GraphDescriptor, - GraphProviderExtendedCapabilities, - GraphProviderStore, - Kit, - Permission, - User, - GraphProviderItem, -} from "@google-labs/breadboard"; - -import * as idb from "idb"; - -import { loadKits } from "./utils/kit-loader.js"; -import GeminiKit from "@google-labs/gemini-kit"; -import PythonWasmKit from "@breadboard-ai/python-wasm"; -import GoogleDriveKit from "@breadboard-ai/google-drive-kit"; - -import { - IDBProjectStoreConfiguration, - IDBProjectStoreProject as IDBBoardServerProject, - LocalStoreData, -} from "./types/idb-types.js"; - -const loadedKits = loadKits([ - GeminiKit, - // TODO: BuildExampleKit, - PythonWasmKit, - GoogleDriveKit, -]); - -// Since IDB does not support various items, like functions, we use -// inflate and deflate functions to handle going into and out of IDB. - -async function inflateConfiguration( - configuration: IDBProjectStoreConfiguration -): Promise { - const secrets = new Map(configuration.secrets); - const allKits = await loadedKits; - const kits: Kit[] = configuration.kits - .map((url) => { - const kit = allKits.find((kit) => kit.url === url); - if (!kit) { - console.warn(`Unable to find kit for ${kit.url}`); - return null; - } - - return kit; - }) - .filter((kit) => kit !== null); - - return { - capabilities: configuration.capabilities, - extensions: [], // TODO. - projects: Promise.resolve([]), - kits, - secrets, - users: configuration.users, - url: new URL(configuration.url), - }; -} - -async function deflateConfiguration( - configuration: BoardServerConfiguration -): Promise { - return { - url: configuration.url.href, - capabilities: configuration.capabilities, - extensions: [], // TODO. - kits: configuration.kits.map((kit) => kit.url), - secrets: configuration.secrets, - users: configuration.users, - }; -} - -async function inflateProject( - project: IDBBoardServerProject -): Promise { - return { - url: new URL(project.url), - metadata: project.metadata, - board: { - url: new URL(project.board.url), - metadata: project.board.metadata, - descriptor: project.board.descriptor, - evaluations: project.board.evaluations, - runs: project.board.runs, - theme: project.board.theme, - }, - }; -} - -async function deflateProject( - project: BoardServerProject -): Promise { - if (!project.board) { - throw new Error("Board not set - unable to deflate"); - } - - return { - url: project.url.href, - metadata: project.metadata, - board: { - url: project.board.url.href, - metadata: project.board.metadata, - descriptor: project.board.descriptor, - evaluations: project.board.evaluations, - runs: project.board.runs, - theme: project.board.theme, - }, - }; -} - -async function createLocalStoreDBIfNeeded(url: string) { - return idb.openDB(IDBBoardServer.parseURL(url), 1, { - upgrade(db) { - db.createObjectStore("configuration", { keyPath: "url" }); - db.createObjectStore("projects", { keyPath: "url" }); - }, - }); -} - -export class IDBBoardServer extends EventTarget implements BoardServer { - public readonly url: URL; - public readonly kits: Kit[]; - public readonly users: User[]; - public readonly secrets = new Map(); - public readonly extensions: BoardServerExtension[] = []; - public readonly capabilities: BoardServerCapabilities = { - connect: false, - disconnect: false, - refresh: false, - watch: false, - preview: false, - }; - - projects: Promise; - - static readonly PROTOCOL = "idb://"; - - static parseURL(url: string) { - if (!url.startsWith(this.PROTOCOL)) { - throw new Error(`Not a local store URL: ${url}`); - } - - return url.replace(/^idb:\/\//, ""); - } - - static async from(url: string, user: User) { - try { - const db = await createLocalStoreDBIfNeeded(url); - - // Obtain and inflate the configuration. - const idbConfiguration = await db.get( - "configuration", - IDBKeyRange.only(url) - ); - if (!idbConfiguration) { - throw new Error(`Unable to retrieve configuration for ${url}`); - } - - const configuration = await inflateConfiguration(idbConfiguration); - return new IDBBoardServer("Browser Storage", configuration, user); - } catch (err) { - console.warn(err); - return null; - } - } - - static async #create(configuration: BoardServerConfiguration) { - const db = await createLocalStoreDBIfNeeded(configuration.url.href); - - const idbConfiguration = await deflateConfiguration(configuration); - await db.put("configuration", idbConfiguration); - - const projects = await configuration.projects; - for (const project of projects) { - const idbProject = await deflateProject(project); - await db.put("projects", idbProject); - } - - db.close(); - } - - static async createDefault(url: URL, user: User) { - const kits = await loadedKits; - this.#create({ - url: new URL(url), - projects: Promise.resolve([]), - kits, - users: [user], - secrets: new Map(), - extensions: [], - capabilities: { - connect: false, - disconnect: false, - refresh: false, - watch: false, - preview: false, - }, - }); - } - - constructor( - public readonly name: string, - configuration: BoardServerConfiguration, - public readonly user: User - ) { - super(); - - this.url = configuration.url; - this.projects = this.#refreshProjects(); - this.kits = configuration.kits; - this.users = configuration.users; - this.secrets = configuration.secrets; - this.extensions = configuration.extensions; - this.capabilities = configuration.capabilities; - } - - // This is a workaround for items() being sync. Since we expect ready() to be - // awaited we know #projects will be populated by the time items() is called. - #projects: BoardServerProject[] = []; - async ready(): Promise { - this.#projects = await this.projects; - } - - isSupported(): boolean { - return true; - } - - extendedCapabilities(): GraphProviderExtendedCapabilities { - return { - modify: true, - connect: false, - disconnect: false, - refresh: false, - watch: false, - preview: false, - }; - } - - async #refreshProjects() { - const db = await createLocalStoreDBIfNeeded(this.url.href); - const projects = await db.getAll("projects").then(async (idbProjects) => { - return await Promise.all( - idbProjects.map((idbProject) => inflateProject(idbProject)) - ); - }); - - db.close(); - return projects; - } - - async load(url: URL): Promise { - const projects = await this.projects; - const project = projects.find((project) => { - return url.pathname.startsWith(project.url.pathname); - }); - if (!project || !project.board) { - return null; - } - - if (project.board.url.href === url.href) { - return project.board.descriptor; - } - - return null; - } - - async save( - url: URL, - descriptor: GraphDescriptor - ): Promise<{ result: boolean; error?: string }> { - const projects = await this.projects; - const project = projects.find((project) => { - return url.pathname.startsWith(project.url.pathname); - }); - if (!project || project.board?.url.href !== url.href) { - return { result: false, error: "Unable to find project" }; - } - - project.board.descriptor = descriptor; - - const db = await createLocalStoreDBIfNeeded(this.url.href); - const idbProject = await deflateProject(project); - await db.put("projects", idbProject); - db.close(); - - return { result: true }; - } - - createBlank(_url: URL): Promise<{ result: boolean; error?: string }> { - throw new Error("Method not implemented."); - } - - async create( - url: URL, - graph: GraphDescriptor - ): Promise<{ result: boolean; error?: string }> { - const access = new Map([ - [ - this.user.username, - { create: true, retrieve: true, update: true, delete: true }, - ], - ]); - - const board = { - metadata: { - owner: this.user.username, - access, - }, - url, - descriptor: graph, - runs: [], - evaluations: [], - }; - - const project: BoardServerProject = { - board, - url, - metadata: { - owner: this.user.username, - access, - title: "", - description: undefined, - icon: undefined, - }, - }; - - const db = await createLocalStoreDBIfNeeded(this.url.href); - const idbProject = await deflateProject(project); - await db.put("projects", idbProject); - - this.projects = this.#refreshProjects(); - return { result: true }; - } - - async delete(url: URL): Promise<{ result: boolean; error?: string }> { - try { - const db = await createLocalStoreDBIfNeeded(this.url.href); - db.delete("projects", IDBKeyRange.only(url.href)); - } catch (err) { - return { result: false, error: "Unable to locate project to delete" }; - } - - this.projects = this.#refreshProjects(); - return { result: true }; - } - - connect(_location?: string, _auth?: unknown): Promise { - throw new Error("Method not implemented."); - } - - disconnect(_location: string): Promise { - throw new Error("Method not implemented."); - } - - async refresh(_location: string): Promise { - await this.projects; - return true; - } - - async createURL(_location: string, fileName: string): Promise { - return `${this.url.href}/${fileName}`; - } - - parseURL(_url: URL): { location: string; fileName: string } { - throw new Error("Method not implemented."); - } - - async restore(): Promise { - await this.projects; - } - - items(): Map { - const items = new Map(); - const projects: [string, GraphProviderItem][] = []; - - const projectNames = new Set(); - for (const project of this.#projects) { - if (!project.board) { - console.warn(`No board set for ${project.url}`); - continue; - } - - let title = project.board.descriptor.title ?? "Untitled Board"; - if (projectNames.has(title) && project.board.descriptor.url) { - const suffix = new URL(project.board.descriptor.url).pathname - .split("/") - .at(-1); - title = `${project.board.descriptor.title ?? "Untitled Board"} [${suffix}]`; - } - - projectNames.add(title); - projects.push([ - title, - { - url: project.url.href, - mine: project.metadata.owner === this.user.username, - readonly: false, - handle: null, - tags: project.board.descriptor.metadata?.tags, - }, - ]); - } - - items.set(this.name, { - items: new Map(projects), - permission: "granted", - title: this.name, - }); - - return items; - } - - startingURL(): URL | null { - throw new Error("Method not implemented."); - } - - watch(_callback: ChangeNotificationCallback): void { - throw new Error("Method not implemented."); - } - - preview(_url: URL): Promise { - throw new Error("Method not implemented."); - } - - canProvide(url: URL) { - if (!url.href.startsWith(IDBBoardServer.PROTOCOL)) { - return false; - } - - return { - save: true, - load: true, - delete: true, - }; - } - - // Users are irrelevant for local stores. - async getAccess(url: URL, user: User): Promise { - const projects = await this.projects; - const project = projects.find((project) => project.url === url); - return ( - project?.metadata.access.get(user.username) ?? { - create: false, - retrieve: false, - update: false, - delete: false, - } - ); - } -} diff --git a/packages/idb-board-server/src/index.ts b/packages/idb-board-server/src/index.ts deleted file mode 100644 index d938d540a19..00000000000 --- a/packages/idb-board-server/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export { IDBBoardServer } from "./idb-board-server.js"; diff --git a/packages/idb-board-server/src/types/idb-types.ts b/packages/idb-board-server/src/types/idb-types.ts deleted file mode 100644 index 913303f83a0..00000000000 --- a/packages/idb-board-server/src/types/idb-types.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - BoardServerCapabilities, - EntityMetadata, - Evaluation, - GraphDescriptor, - Run, - Secrets, - User, -} from "@google-labs/breadboard"; -import type * as idb from "idb"; - -export interface IDBProjectStoreConfiguration { - url: string; - kits: string[]; - users: User[]; - secrets: Secrets; - extensions: string[]; - capabilities: BoardServerCapabilities; -} - -export interface IDBProjectStoreBoard { - theme?: string; - descriptor: GraphDescriptor; - runs?: Run[]; - evaluations?: Evaluation[]; - url: string; - metadata: EntityMetadata; -} - -export interface IDBProjectStoreProject { - board: IDBProjectStoreBoard; - url: string; - metadata: EntityMetadata; -} - -export interface LocalStoreData extends idb.DBSchema { - configuration: { - key: "url"; - value: IDBProjectStoreConfiguration; - }; - projects: { - key: "url"; - value: IDBProjectStoreProject; - }; -} diff --git a/packages/idb-board-server/src/utils/kit-loader.ts b/packages/idb-board-server/src/utils/kit-loader.ts deleted file mode 100644 index b6f63264465..00000000000 --- a/packages/idb-board-server/src/utils/kit-loader.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { KitConstructor, Kit, asRuntimeKit } from "@google-labs/breadboard"; -import { load } from "@google-labs/breadboard/kits"; - -export const loadKits = async (kitConstructors: KitConstructor[]) => { - const loadedKits = kitConstructors.map((kitConstructor) => - asRuntimeKit(kitConstructor) - ); - - const base = new URL(`${self.location.origin}/kits.json`); - const response = await fetch(base); - const kitList = await response.json(); - - const kits = await Promise.all( - kitList.map(async (kitURL: string) => { - // workaround for vite prod/dev mode difference - if (kitURL.endsWith(".js") && import.meta.env.DEV) { - kitURL = `/src/${kitURL.replace(/\.js$/, ".ts")}`; - } - return await load(new URL(kitURL, base)); - }) - ); - - return [...loadedKits, ...kits]; -}; diff --git a/packages/idb-board-server/tsconfig.json b/packages/idb-board-server/tsconfig.json deleted file mode 100644 index 40a3e9972c4..00000000000 --- a/packages/idb-board-server/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "ESNext", - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - "experimentalDecorators": true, - "useDefineForClassFields": false, - "outDir": "dist", - - /* Bundler mode */ - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": false, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "types": ["vite/client"] - }, - "include": ["src/**/*.ts", "tests/**/*.ts"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/import/.eslintrc b/packages/import/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/import/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/import/.npmignore b/packages/import/.npmignore deleted file mode 100644 index 7ddb2133685..00000000000 --- a/packages/import/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -tsconfig.tsbuildinfo diff --git a/packages/import/CHANGELOG.md b/packages/import/CHANGELOG.md deleted file mode 100644 index 71a12b90f8e..00000000000 --- a/packages/import/CHANGELOG.md +++ /dev/null @@ -1,208 +0,0 @@ -# @breadboard-ai/import - -## 0.1.10 - -### Patch Changes - -- Updated dependencies [703f17d] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [4dadf16] -- Updated dependencies [8f9fddf] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [9797718] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [a039d2e] -- Updated dependencies [9783ba8] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [d7606d3] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] - - @google-labs/breadboard@0.27.0 - -## 0.1.9 - -### Patch Changes - -- Updated dependencies [7d46a63] - - @google-labs/breadboard@0.26.0 - -## 0.1.8 - -### Patch Changes - -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @google-labs/breadboard@0.25.0 - -## 0.1.7 - -### Patch Changes - -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [1dc645a] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [c04cff0] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - -## 0.1.6 - -### Patch Changes - -- Updated dependencies [1e1be2a] -- Updated dependencies [2b094a3] -- Updated dependencies [fa93c3f] -- Updated dependencies [215bd15] -- Updated dependencies [2b9ef5b] -- Updated dependencies [a0852df] -- Updated dependencies [2312443] -- Updated dependencies [6ffa89c] - - @google-labs/breadboard@0.23.0 - -## 0.1.5 - -### Patch Changes - -- Updated dependencies [a925cf0] -- Updated dependencies [5cf08f1] -- Updated dependencies [ffbf163] -- Updated dependencies [8928fb7] -- Updated dependencies [d6706f2] -- Updated dependencies [5447426] -- Updated dependencies [7e1f01c] - - @google-labs/breadboard@0.22.0 - -## 0.1.4 - -### Patch Changes - -- Updated dependencies [5a55b7d] -- Updated dependencies [74ade20] -- Updated dependencies [59dd0f5] -- Updated dependencies [417323c] -- Updated dependencies [b3aa884] -- Updated dependencies [3d7b4a7] -- Updated dependencies [7af14cf] -- Updated dependencies [fea8967] -- Updated dependencies [778f7aa] -- Updated dependencies [808f5e2] -- Updated dependencies [e0fdbc3] -- Updated dependencies [54b03b9] -- Updated dependencies [810d7fd] -- Updated dependencies [14853d5] -- Updated dependencies [8798514] -- Updated dependencies [eb64b9a] -- Updated dependencies [32a48a3] -- Updated dependencies [cd73b17] -- Updated dependencies [81d82fe] -- Updated dependencies [2a7531b] -- Updated dependencies [7c1b4cb] -- Updated dependencies [702cfe1] -- Updated dependencies [bebd96e] -- Updated dependencies [91cb723] -- Updated dependencies [3e10f0f] -- Updated dependencies [c53ca01] -- Updated dependencies [4c681cb] -- Updated dependencies [fb2e584] -- Updated dependencies [9491266] -- Updated dependencies [2ace620] -- Updated dependencies [fcef799] -- Updated dependencies [37418d9] -- Updated dependencies [083f69c] -- Updated dependencies [5b03d96] -- Updated dependencies [f0d8d67] -- Updated dependencies [836389d] -- Updated dependencies [225c7cc] - - @google-labs/breadboard@0.21.0 - -## 0.1.3 - -### Patch Changes - -- Updated dependencies [8097177] -- Updated dependencies [cec6d54] -- Updated dependencies [3397974] -- Updated dependencies [ab9a4ce] -- Updated dependencies [a35406c] -- Updated dependencies [477e6e6] - - @google-labs/breadboard@0.20.0 - -## 0.1.2 - -### Patch Changes - -- Updated dependencies [63eb779] - - @google-labs/breadboard@0.19.0 - -## 0.1.1 - -### Patch Changes - -- Updated dependencies [cef20ca] -- Updated dependencies [fbf7a83] -- Updated dependencies [54baba8] -- Updated dependencies [49c3aa1] -- Updated dependencies [cdc23bb] -- Updated dependencies [416aed2] -- Updated dependencies [a1fcaea] -- Updated dependencies [c3ed6a7] -- Updated dependencies [3d48482] -- Updated dependencies [f2eda0b] -- Updated dependencies [626139b] -- Updated dependencies [bd44e29] -- Updated dependencies [43da00a] -- Updated dependencies [c3587e1] -- Updated dependencies [3f9507d] - - @google-labs/breadboard@0.18.0 - -## 0.1.0 - -### Minor Changes - -- 7e91ef0: CLI now uses OpenAPI import package - -### Patch Changes - -- Updated dependencies [c3cb25f] -- Updated dependencies [ae79e4a] -- Updated dependencies [72c5c6b] -- Updated dependencies [dd810dd] -- Updated dependencies [c5ba396] -- Updated dependencies [7bafa40] -- Updated dependencies [2932f4b] -- Updated dependencies [51159c4] -- Updated dependencies [6f9ba52] - - @google-labs/breadboard@0.17.0 diff --git a/packages/import/README.md b/packages/import/README.md deleted file mode 100644 index 1744eefe29f..00000000000 --- a/packages/import/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Breadboard Import Library - -The library that powers the Breadboard Import feature in the Breadboard CLI. diff --git a/packages/import/package.json b/packages/import/package.json deleted file mode 100644 index 419cdfad214..00000000000 --- a/packages/import/package.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "name": "@breadboard-ai/import", - "version": "0.1.10", - "description": "The OpenAPI import library for Breadboard", - "main": "./dist/src/index.js", - "exports": "./dist/src/index.js", - "types": "./dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "test": "wireit", - "build": "wireit", - "lint": "wireit" - }, - "repository": { - "directory": "packages/import", - "type": "git", - "url": "https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src" - ], - "ava": { - "timeout": "30s", - "files": [ - "tests/**/*.ts" - ], - "workerThreads": false, - "typescript": { - "rewritePaths": { - "./": "dist/" - }, - "compile": false - } - }, - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "typescript": "^5.6.2" - }, - "dependencies": { - "openapi-types": "^12.1.3", - "yaml": "^2.5.1", - "@google-labs/breadboard": "^0.27.0" - }, - "wireit": { - "build": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "../breadboard:build:tsc" - ], - "files": [ - "src/**/*.js", - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - }, - "test": { - "command": "ava", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build" - ] - } - } -} diff --git a/packages/import/src/gates.ts b/packages/import/src/gates.ts deleted file mode 100644 index a054638b370..00000000000 --- a/packages/import/src/gates.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { AtLeastV3Document, AtLeastV3ReferenceObject } from "./types.js"; - -export function isReferenceObject( - obj: object -): obj is AtLeastV3ReferenceObject { - return "$ref" in obj; -} - -export function isOpenAPI(json: object): json is AtLeastV3Document { - if ("openapi" in json == false) { - throw new Error("Not an Open API spec."); - } - - if ("servers" in json == false) { - throw new Error("No servers in Open API spec."); - } - - if ("paths" in json == false) { - throw new Error("No paths in Open API spec."); - } - - return true; -} diff --git a/packages/import/src/generateAPISpecs.ts b/packages/import/src/generateAPISpecs.ts deleted file mode 100644 index afb58034f89..00000000000 --- a/packages/import/src/generateAPISpecs.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { isReferenceObject } from "./gates.js"; -import { - parseParametersFromRequest, - parseParametersFromPathOrQueryString, -} from "./parseParameters.js"; -import type { - APISpec, - AtLeastV3Document, - AtLeastV3Operation, - AtLeastV3ReferenceObject, - AtLeastV3SecuritySchemeObject, -} from "./types.js"; - -/* - If there is no operation ID, we need to generate one from the path, but format it like a JS function name. - */ - -const inferOperationId = (path: string, method: string) => { - const newName = path - .split("/") - .map((part) => - part.length == 0 ? part : part[0].toUpperCase() + part.slice(1) - ) - .join("") - .replace(/[.-]/g, "") // Remove dashes and dots - .replace(/[{}]/g, ""); // Remove curly braces (need to improve this) - - return `${method}${newName}`; -}; - -export const generateAPISpecs = (json: AtLeastV3Document): APISpec[] => { - const { paths } = json; - - const baseUrl = json.servers?.[0].url; - - if (baseUrl == undefined) { - throw new Error("No base URL in Open API spec."); - } - - const apis: [string, string, AtLeastV3Operation][] = []; - // Generate a list of APIs - for (const apiPath in paths) { - const pathInfo = paths[apiPath]; - if (pathInfo == undefined) { - continue; - } - const globalPathParams = pathInfo.parameters || []; - - if (pathInfo.get != undefined) { - pathInfo.get.parameters = pathInfo.get.parameters || []; - pathInfo.get.parameters.push(...globalPathParams); - apis.push([apiPath, "get", pathInfo.get]); - } - if (pathInfo.post != undefined) { - pathInfo.post.parameters = pathInfo.post.parameters || []; - pathInfo.post.parameters.push(...globalPathParams); - apis.push([apiPath, "post", pathInfo.post]); - } - } - - const outputApis = apis.map(([path, method, data]) => { - if (data instanceof String) return; - - const operationId = data.operationId || inferOperationId(path, method); - - // All parameters, path or query are held in the parameters array ( but might be a reference) - const parameters = - data.parameters == undefined - ? [] - : parseParametersFromPathOrQueryString(json, data.parameters); - - const requestBody = - data.requestBody == undefined - ? {} - : parseParametersFromRequest(json, data.requestBody); - - let secrets: - | AtLeastV3SecuritySchemeObject - | AtLeastV3ReferenceObject - | undefined = undefined; - // We can only support Bearer tokens for now. - if ( - json.components != undefined && - json.components.securitySchemes != undefined - ) { - // Check to see if global security is defined, it's the same type and && it is a bearer token. - const bearerSecurity = Object.entries( - json.components.securitySchemes - ).find(([securityMethodKey, securityValue]) => { - if (isReferenceObject(securityValue)) { - return false; - } - - if (json.security == undefined) { - return false; - } - - const security = json.security.find((item) => { - return securityMethodKey in item; - }); - - return ( - security && - securityValue.type == "http" && - securityValue.scheme == "bearer" - ); - }); - - if (bearerSecurity != undefined) { - secrets = bearerSecurity[1]; - } - } - - return { - operationId, - url: baseUrl.replace(/\/$/, "") + path, - method: method.toUpperCase(), - description: data.description || "", - summary: data.summary || "", - parameters, - requestBody, - secrets, - }; - }); - - return outputApis as APISpec[]; -}; diff --git a/packages/import/src/index.ts b/packages/import/src/index.ts deleted file mode 100644 index 661ceca999b..00000000000 --- a/packages/import/src/index.ts +++ /dev/null @@ -1,337 +0,0 @@ -import { Board, NodeValue } from "@google-labs/breadboard"; -import { loadOpenAPI } from "./loader.js"; -import { isOpenAPI } from "./gates.js"; -import { generateAPISpecs } from "./generateAPISpecs.js"; - -import type { - APISpec, - AtLeastV3ReferenceObject, - ExcludedParameter, - AtLeastV3Document, - AtLeastV3MediaObjectMap, - AtLeastV3SecuritySchemeObject, -} from "./types.js"; - -export type * from "./types.js"; - -export class OpenAPIBoardBuilder { - #url: string; - #board: Board | undefined; - #json: AtLeastV3Document | undefined; - constructor(url: string) { - this.#url = url; - } - - private async load() { - const url = this.#url; - const json = await loadOpenAPI(url); - if (json == undefined) { - throw new Error(`Unable to parse OpenAPI spec from ${url}`); - } - - const openAPI = isOpenAPI(json); - - if (openAPI == false) { - throw new Error("Not an Open API v3 or v3.1 spec."); - } - - this.#json = json; - } - - public async *build(): AsyncGenerator<{ board: Board; apiSpec: APISpec }> { - await this.load(); - if (this.#json == undefined) { - throw new Error("Unable to load OpenAPI spec."); - } - const apiSpecs = generateAPISpecs(this.#json); - const json = this.#json; - for (const apiSpec of apiSpecs) { - if (apiSpec == undefined) { - throw new Error("Unable to generate API specs."); - } - const board = new Board({ - title: apiSpec?.operationId, - description: apiSpec?.description, - version: "0.0.1", - }); - - // Creates the URL, path-inputs, and mergeHTTPHeaders nodes for the board. - buildURL(board, apiSpec); - - buildSecrets(apiSpec, json, board); - - buildHTTPHeaders(apiSpec, board); - - board.addNode({ - id: "fetch", - type: "fetch", - configuration: { - method: apiSpec?.method, - }, - }); - - buildRequestBody(apiSpec, board); - - board.addEdge({ - from: "fetch", - to: "output", - out: "response", - in: "api_json_response", - }); - - board.addNode({ - id: "output", - type: "output", - configuration: { - schema: { - type: "object", - properties: { - api_json_response: { - type: "object", - title: "API response", - description: "The response from the API call (JSON)", - }, - }, - }, - }, - }); - - yield { board, apiSpec }; - } - } -} - -function buildRequestBody( - api: { - operationId: string; - url: string; - method: string; - description: string | undefined; - summary: string | undefined; - parameters: ExcludedParameter[]; - requestBody: AtLeastV3MediaObjectMap; - secrets: - | AtLeastV3ReferenceObject - | AtLeastV3SecuritySchemeObject - | undefined; - }, - board: Board -) { - if (Object.keys(api.requestBody).length > 0) { - // Only support JSON Schema for now. If you need XML, talk to Paul. - board.addNode({ - id: "input-requestBody", - type: "input", - configuration: { - schema: { - type: "object", - properties: { - requestBody: { - type: "object", - title: "requestBody", - description: "The request body for the API call (JSON)", - }, - }, - }, - }, - }); - - board.addEdge({ - from: "input-requestBody", - to: "fetch", - out: "requestBody", - in: "body", - }); - } -} - -function buildSecrets( - api: { - operationId: string; - url: string; - method: string; - description: string | undefined; - summary: string | undefined; - parameters: ExcludedParameter[]; - requestBody: AtLeastV3MediaObjectMap; - secrets: - | AtLeastV3ReferenceObject - | AtLeastV3SecuritySchemeObject - | undefined; - }, - json: AtLeastV3Document, - board: Board -) { - const hasKeyInParameters = - api.parameters.find((param) => param.name == "key") != undefined; - if (api.secrets != undefined || hasKeyInParameters) { - // We generate a secret node for the API key based on the name of the API - const apiKeyName = `${json.info.title - .replace(/[^a-zA-Z0-9]+/g, "_") - .toUpperCase()}_KEY`; - - board.addNode({ - id: "input-secrets", - type: "secrets", - configuration: { - keys: [apiKeyName], - }, - }); - - if (hasKeyInParameters) { - // This is a hack. If there query_string has a "key" parameter, we need to add it to the URL. - board.addEdge({ - from: "input-secrets", - to: "url", - out: apiKeyName, - in: "key", - }); - } else { - // We are expecting the secrets to be a Bearer token. - board.addEdge({ - from: "input-secrets", - to: "mergeHTTPHeaders", - out: apiKeyName, - in: "Authorization_Key", - }); - } - } -} - -/* - Creates the URL node and the path-inputs node for the board. - - The URL is a combination of the URL from the API and the parameters from the API. -*/ -function buildURL( - board: Board, - api: { - operationId: string; - url: string; - method: string; - description: string | undefined; - summary: string | undefined; - parameters: ExcludedParameter[]; - requestBody: AtLeastV3MediaObjectMap; - secrets: - | AtLeastV3ReferenceObject - | AtLeastV3SecuritySchemeObject - | undefined; - } -) { - if (api.parameters.length > 0) { - // For each QS or Path parameter on the API, we need to add an input node to the board. - const params: Record = {}; - - for (const param of api.parameters) { - if (param.name == undefined) { - continue; - } - params[param.name] = { - title: param?.name, - type: param?.schema.type, - description: param?.description || `The data for ${param.name}`, - example: param?.schema?.example, - }; - - board.addEdge({ - from: "path-inputs", - to: "url", - out: param?.name, - in: param?.name, - optional: param.required == undefined || param?.required == false, - }); - } - - board.addNode({ - id: "path-inputs", - type: "input", - configuration: { - schema: { - type: "object", - properties: params, - required: api.parameters - .filter((param) => param?.required) - .map((param) => param?.name), - }, - }, - }); - } - - board.addNode({ - id: "url", - type: "urlTemplate", - configuration: { - template: `${api.url}?${api.parameters - .map((param) => `{&${param?.name}}`) - .join("")}`, - }, - }); - - board.addEdge({ - from: "url", - to: "fetch", - out: "url", - in: "url", - }); -} - -function buildHTTPHeaders( - api: { - operationId: string; - url: string; - method: string; - description: string | undefined; - summary: string | undefined; - parameters: ExcludedParameter[]; - requestBody: AtLeastV3MediaObjectMap; - secrets: - | AtLeastV3ReferenceObject - | AtLeastV3SecuritySchemeObject - | undefined; - }, - board: Board -) { - const authorizationHeader = api.secrets - ? { - Authorization: `Bearer `, - } - : {}; - - const contentTypeHeader = api.requestBody - ? { - "Content-Type": "application/json", - } - : {}; - - board.addNode({ - id: "mergeHTTPHeaders", - type: "runJavascript", - - configuration: { - raw: true, - code: `function(inputs) { - const headers = {}; - - if (inputs.Authorization_Key != undefined) { - headers["Authorization"] = "Bearer " + inputs.Authorization_Key; - } - - if ("Content-Type" in inputs) { - headers["Content-Type"] = inputs["Content-Type"]; - } - - return { headers }; - }`, - ...contentTypeHeader, - ...authorizationHeader, - }, - }); - - board.addEdge({ - from: "mergeHTTPHeaders", - to: "fetch", - out: "headers", - in: "headers", - }); -} diff --git a/packages/import/src/loader.ts b/packages/import/src/loader.ts deleted file mode 100644 index 4e3b45642b6..00000000000 --- a/packages/import/src/loader.ts +++ /dev/null @@ -1,30 +0,0 @@ -import yaml from "yaml"; -import { readFile } from "fs/promises"; -import type { AtLeastV3Document } from "./types.js"; - -export async function loadOpenAPI(url: string): Promise { - let openAPIData = ""; - try { - if (url.startsWith("file://")) { - openAPIData = await readFile(url.replace("file://", ""), { - encoding: "utf-8", - }); - } else { - openAPIData = await (await fetch(url)).text(); - } - } catch (e) { - throw new Error(`Unable to fetch OpenAPI spec from ${url}`); - } - - try { - return yaml.parse(openAPIData); - } catch (yamlLoadError) { - try { - return JSON.parse(openAPIData); - } catch (jsonLoadError) { - throw new Error( - `Unable to parse OpenAPI spec from ${url}. It's not a valid JSON or YAML file.` - ); - } - } -} diff --git a/packages/import/src/parseParameters.ts b/packages/import/src/parseParameters.ts deleted file mode 100644 index 5a7e6bce2aa..00000000000 --- a/packages/import/src/parseParameters.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { OpenAPI } from "openapi-types"; -import type { - AtLeastV3ReferenceObject, - AtLeastV3RequestBodyObject, - ExcludedParameter, - ExcludeRequestBody, - MediaTypeObject, - SupportedOpenAPIDocuments, -} from "./types.js"; -import { isReferenceObject } from "./gates.js"; - -export function parseParametersFromRequest< - D extends SupportedOpenAPIDocuments, - P extends AtLeastV3ReferenceObject | AtLeastV3RequestBodyObject, ->(json: D, request: P): ExcludeRequestBody["content"] { - if (isReferenceObject(request)) { - return {}; // Can't deal with this yet. - } - - if (request.content == undefined) { - return {}; - } - const requestThing = Object.entries(request.content).filter( - ([contentType, requestParams]) => { - if (requestParams == undefined) { - return false; - } - - if (requestParams.schema == undefined) { - return false; - } - - if (isReferenceObject(requestParams.schema) == false) { - return true; - } - - return requestParams.schema.$ref.startsWith("#"); - } - ); - - const accumulator: ExcludeRequestBody["content"] = {}; - for (const [contentType, requestParams] of requestThing) { - if (requestParams == undefined || requestParams.schema == undefined) { - continue; - } - - if (isReferenceObject(requestParams.schema)) { - const refKey = requestParams.schema.$ref; - - const pathParts = refKey.replace(/^#\//, "").split("/"); - let obj = json as unknown as Record; - - if (obj == undefined) { - throw new Error("No JSON object"); - } - - for (const part of pathParts) { - obj = obj[part] as Record; - } - - if ("description" in obj == false) { - obj.description = `Request POST data (format: ${contentType})`; - } - - accumulator[contentType] = { - schema: requestParams.schema, - }; - } else { - accumulator[contentType] = { - schema: requestParams.schema, - }; - } - } - return accumulator; -} - -export function parseParametersFromPathOrQueryString< - D extends SupportedOpenAPIDocuments, - P extends OpenAPI.Parameter[], ->(json: D, parameters: P): ExcludedParameter[] { - return parameters - .filter((param) => { - if (isReferenceObject(param) == false) { - return true; - } - - return param.$ref.startsWith("#"); - }) - .map((param) => { - // We can only manage reference objects for now. - if (isReferenceObject(param)) { - // We will convert a reference object to a parameter object. - const pathParts = param.$ref.replace(/^#\//, "").split("/"); - let obj = json as unknown as Record; - - for (const part of pathParts) { - obj = obj[part] as Record; - } - - return obj as unknown as ExcludedParameter; - } else { - return param as unknown as ExcludedParameter; - } - }) as ExcludedParameter[]; -} diff --git a/packages/import/src/types.d.ts b/packages/import/src/types.d.ts deleted file mode 100644 index 3a3d84537e9..00000000000 --- a/packages/import/src/types.d.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { OpenAPIV3, OpenAPIV3_1 } from "openapi-types"; - -// We only support OpenAPI v3 and v3.1, the types here just make it cleaner in the other parsing logic. - -export type AtLeastV3Document = OpenAPIV3.Document | OpenAPIV3_1.Document; - -export type SupportedOpenAPIDocuments = OpenAPI.Document; - -export type AtLeastV3ReferenceObject = - | OpenAPIV3.ReferenceObject - | OpenAPIV3_1.ReferenceObject; - -export type AtLeastV3SecuritySchemeObject = - | OpenAPIV3.SecuritySchemeObject - | OpenAPIV3_1.SecuritySchemeObject; - -export type AtLeastV3MediaObjectMap = - | { [media: string]: OpenAPIV3.MediaTypeObject } - | { [media: string]: OpenAPIV3_1.MediaTypeObject }; - -export type AtLeastV3RequestBodyObject = - | OpenAPIV3.RequestBodyObject - | OpenAPIV3_1.RequestBodyObject; - -export type AtLeastV3Operation = - | OpenAPIV3.OperationObject - | OpenAPIV3_1.OperationObject; - -export type APISpec = { - operationId: string; - url: string; - method: string; - description: string; - summary: string; - parameters: ExcludedParameter[]; - requestBody: AtLeastV3MediaObjectMap; - secrets: AtLeastV3SecuritySchemeObject | AtLeastV3ReferenceObject | undefined; -}; - -export type ExcludeRequestBody = Exclude< - AtLeastV3RequestBodyObject, - AtLeastV3ReferenceObject ->; - -export type ExcludedParameter = Exclude< - OpenAPI.Parameter, - AtLeastV3ReferenceObject ->; - -export type MediaTypeObject = - | OpenAPIV3_1.MediaTypeObject - | OpenAPIV3.MediaTypeObject; diff --git a/packages/import/tests/index.ts b/packages/import/tests/index.ts deleted file mode 100644 index caead52d710..00000000000 --- a/packages/import/tests/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import test from "ava"; - -test("default", (t) => { - t.pass(); -}); diff --git a/packages/import/tsconfig.json b/packages/import/tsconfig.json deleted file mode 100644 index 1ff943cd641..00000000000 --- a/packages/import/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "outDir": "./dist" - }, - "include": ["src/**/*", "tests/**/*"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/json-kit/.eslintrc b/packages/json-kit/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/json-kit/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/json-kit/.npmignore b/packages/json-kit/.npmignore deleted file mode 100644 index 7ddb2133685..00000000000 --- a/packages/json-kit/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -tsconfig.tsbuildinfo diff --git a/packages/json-kit/CHANGELOG.md b/packages/json-kit/CHANGELOG.md deleted file mode 100644 index b2a880264b5..00000000000 --- a/packages/json-kit/CHANGELOG.md +++ /dev/null @@ -1,448 +0,0 @@ -# Changelog - -## 0.3.8 - -### Patch Changes - -- 54c8197: Make build API kit function async -- 0273985: Convert validateJson to build API -- 78d6394: Add a partial build API kit to json-kit -- e74ee2f: Convert schemish to build API -- Updated dependencies [49e2740] -- Updated dependencies [54c8197] -- Updated dependencies [703f17d] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [8f9fddf] -- Updated dependencies [2fa05f0] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [f71bcfb] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [3188607] -- Updated dependencies [9797718] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [8330f0c] -- Updated dependencies [a039d2e] -- Updated dependencies [1423647] -- Updated dependencies [9783ba8] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [91fe8bb] -- Updated dependencies [100fc95] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [5834c81] -- Updated dependencies [d7606d3] -- Updated dependencies [0ef793f] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] - - @breadboard-ai/build@0.10.0 - - @google-labs/breadboard@0.27.0 - -## 0.3.7 - -### Patch Changes - -- Updated dependencies [bbcdd2d] -- Updated dependencies [9ed58cf] -- Updated dependencies [7f2ef33] -- Updated dependencies [7d46a63] -- Updated dependencies [bac2e35] -- Updated dependencies [ec2fedd] - - @breadboard-ai/build@0.9.1 - - @google-labs/breadboard@0.26.0 - -## 0.3.6 - -### Patch Changes - -- Updated dependencies [cc5f4b6] -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [a940b87] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [374ea85] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [f93ec06] -- Updated dependencies [398bf4f] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @breadboard-ai/build@0.9.0 - - @google-labs/breadboard@0.25.0 - -## 0.3.5 - -### Patch Changes - -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [1dc645a] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [c04cff0] -- Updated dependencies [d88c37b] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - - @breadboard-ai/build@0.8.1 - -## 0.3.4 - -### Patch Changes - -- 8db38aa: Exporting jsonata node from index -- 9a2ffab: Unpin @breadboard-ai/build dependency from being overly constrained -- Updated dependencies [ad8aa22] -- Updated dependencies [1e1be2a] -- Updated dependencies [2b094a3] -- Updated dependencies [fa93c3f] -- Updated dependencies [f78ec0a] -- Updated dependencies [215bd15] -- Updated dependencies [2b9ef5b] -- Updated dependencies [a0852df] -- Updated dependencies [2312443] -- Updated dependencies [b76f9a1] -- Updated dependencies [6ffa89c] -- Updated dependencies [15ae381] - - @breadboard-ai/build@0.8.0 - - @google-labs/breadboard@0.23.0 - -## 0.3.3 - -### Patch Changes - -- Updated dependencies [a925cf0] -- Updated dependencies [da43bb5] -- Updated dependencies [5cf08f1] -- Updated dependencies [ffbf163] -- Updated dependencies [8928fb7] -- Updated dependencies [9d93cf8] -- Updated dependencies [d6706f2] -- Updated dependencies [5447426] -- Updated dependencies [26e1099] -- Updated dependencies [7e1f01c] - - @google-labs/breadboard@0.22.0 - - @breadboard-ai/build@0.7.1 - -## 0.3.2 - -### Patch Changes - -- 29774aa: Update dependency package versions. - -## 0.3.1 - -### Patch Changes - -- 3d7b4a7: Introduce optional `help` metadata for graphs and kits. -- fcef799: Update `help` to have description and URL -- Updated dependencies [5a55b7d] -- Updated dependencies [74ade20] -- Updated dependencies [59dd0f5] -- Updated dependencies [417323c] -- Updated dependencies [b3aa884] -- Updated dependencies [00825d5] -- Updated dependencies [3d7b4a7] -- Updated dependencies [7af14cf] -- Updated dependencies [fea8967] -- Updated dependencies [778f7aa] -- Updated dependencies [808f5e2] -- Updated dependencies [e0fdbc3] -- Updated dependencies [54b03b9] -- Updated dependencies [810d7fd] -- Updated dependencies [14853d5] -- Updated dependencies [8798514] -- Updated dependencies [eb64b9a] -- Updated dependencies [32a48a3] -- Updated dependencies [cd73b17] -- Updated dependencies [81d82fe] -- Updated dependencies [2a7531b] -- Updated dependencies [7c1b4cb] -- Updated dependencies [702cfe1] -- Updated dependencies [bebd96e] -- Updated dependencies [91cb723] -- Updated dependencies [3e10f0f] -- Updated dependencies [c53ca01] -- Updated dependencies [6ada218] -- Updated dependencies [4c681cb] -- Updated dependencies [fb2e584] -- Updated dependencies [9491266] -- Updated dependencies [2ace620] -- Updated dependencies [c5f8e4f] -- Updated dependencies [fcef799] -- Updated dependencies [37418d9] -- Updated dependencies [083f69c] -- Updated dependencies [5b03d96] -- Updated dependencies [f0d8d67] -- Updated dependencies [836389d] -- Updated dependencies [225c7cc] -- Updated dependencies [06c3f57] - - @google-labs/breadboard@0.21.0 - - @breadboard-ai/build@0.7.0 - -## 0.3.0 - -### Minor Changes - -- 7936d8b: Convert jsonata node to new API - -### Patch Changes - -- cdcbcdb: Update jsonata node for new $error behavior -- Updated dependencies [8097177] -- Updated dependencies [29eda71] -- Updated dependencies [f60cb06] -- Updated dependencies [cec6d54] -- Updated dependencies [87eb8fe] -- Updated dependencies [f97a4d5] -- Updated dependencies [60a18c5] -- Updated dependencies [b0ed6f3] -- Updated dependencies [4957dc5] -- Updated dependencies [a209c51] -- Updated dependencies [3397974] -- Updated dependencies [7368fdd] -- Updated dependencies [c9c0e06] -- Updated dependencies [c1acf24] -- Updated dependencies [3920805] -- Updated dependencies [ab9a4ce] -- Updated dependencies [3b2bb4a] -- Updated dependencies [a35406c] -- Updated dependencies [31cf016] -- Updated dependencies [ab43276] -- Updated dependencies [477e6e6] -- Updated dependencies [cdcbcdb] -- Updated dependencies [791ec2a] -- Updated dependencies [c0293c9] -- Updated dependencies [b6f5644] -- Updated dependencies [43edef6] - - @google-labs/breadboard@0.20.0 - - @breadboard-ai/build@0.6.0 - -## 0.2.2 - -### Patch Changes - -- Updated dependencies [63eb779] - - @google-labs/breadboard@0.19.0 - -## 0.2.1 - -### Patch Changes - -- 416aed2: Introduce `metadata` for `NodeHandler` entries, teaching node types in Kits to describe themselves. -- Updated dependencies [cef20ca] -- Updated dependencies [fbf7a83] -- Updated dependencies [54baba8] -- Updated dependencies [49c3aa1] -- Updated dependencies [cdc23bb] -- Updated dependencies [416aed2] -- Updated dependencies [a1fcaea] -- Updated dependencies [c3ed6a7] -- Updated dependencies [3d48482] -- Updated dependencies [f2eda0b] -- Updated dependencies [626139b] -- Updated dependencies [bd44e29] -- Updated dependencies [43da00a] -- Updated dependencies [c3587e1] -- Updated dependencies [3f9507d] - - @google-labs/breadboard@0.18.0 - -## 0.2.0 - -### Minor Changes - -- 914353c: validateJson node can now accept invalid schemas at the users discression - -### Patch Changes - -- Updated dependencies [c3cb25f] -- Updated dependencies [ae79e4a] -- Updated dependencies [72c5c6b] -- Updated dependencies [dd810dd] -- Updated dependencies [c5ba396] -- Updated dependencies [7bafa40] -- Updated dependencies [2932f4b] -- Updated dependencies [51159c4] -- Updated dependencies [6f9ba52] - - @google-labs/breadboard@0.17.0 - -## 0.1.5 - -### Patch Changes - -- Updated dependencies [ad9c233] -- Updated dependencies [65d869b] -- Updated dependencies [417cdf5] -- Updated dependencies [cf0ee4f] -- Updated dependencies [43cbed7] -- Updated dependencies [ff6433c] -- Updated dependencies [5382365] -- Updated dependencies [0e7f106] -- Updated dependencies [9ea6ba0] -- Updated dependencies [ffd2a6c] - - @google-labs/breadboard@0.16.0 - -## 0.1.4 - -### Patch Changes - -- Updated dependencies [76da09d] -- Updated dependencies [938015d] - - @google-labs/breadboard@0.15.0 - -## 0.1.3 - -### Patch Changes - -- Updated dependencies [e8d0737] - - @google-labs/breadboard@0.14.0 - -## 0.1.2 - -### Patch Changes - -- Updated dependencies [faf1e12] -- Updated dependencies [51a38c0] -- Updated dependencies [d49b80e] -- Updated dependencies [9326bd7] -- Updated dependencies [fbad949] - - @google-labs/breadboard@0.13.0 - -## 0.1.1 - -### Patch Changes - -- 49c25aa: Add describers for a few nodes. -- 5bc47be: Strip out stuff outside of the markdown code block -- Updated dependencies [99446b8] -- Updated dependencies [866fc36] -- Updated dependencies [a8bab08] -- Updated dependencies [decfa29] -- Updated dependencies [f005b3b] -- Updated dependencies [dcfdc37] -- Updated dependencies [d971aad] -- Updated dependencies [048e8ec] -- Updated dependencies [dc35601] -- Updated dependencies [9cda2ff] -- Updated dependencies [60bd63c] -- Updated dependencies [764ccda] -- Updated dependencies [04d5420] -- Updated dependencies [56b90a4] -- Updated dependencies [1b48826] -- Updated dependencies [e648f64] -- Updated dependencies [ad5c1be] -- Updated dependencies [4a4a1f6] -- Updated dependencies [bac9bb1] -- Updated dependencies [3e8cfcf] -- Updated dependencies [986af39] -- Updated dependencies [3c497b0] -- Updated dependencies [eabd97b] -- Updated dependencies [2008f69] -- Updated dependencies [c0f785a] -- Updated dependencies [a8fc3f3] -- Updated dependencies [32cfbaf] -- Updated dependencies [8dc4e00] -- Updated dependencies [6438930] -- Updated dependencies [dd2cce6] -- Updated dependencies [cac4f4f] -- Updated dependencies [b1fc53b] -- Updated dependencies [ef05634] -- Updated dependencies [c208cfc] - - @google-labs/breadboard@0.12.0 - -## 0.1.0 - -### Minor Changes - -- 3f3f090: Teach `jsonata` and `invoke` nodes to better describe themselves. - -### Patch Changes - -- 56954c1: Introduce `InspectableNode.ports`, which enumerates ports of a node. -- Updated dependencies [c19513e] -- Updated dependencies [2237a4c] -- Updated dependencies [bd68ebd] -- Updated dependencies [9a76a87] -- Updated dependencies [ea652f3] -- Updated dependencies [56954c1] -- Updated dependencies [0085ee2] -- Updated dependencies [0ef9ec5] -- Updated dependencies [ee00249] -- Updated dependencies [c13513f] -- Updated dependencies [56ccae5] -- Updated dependencies [4920d90] -- Updated dependencies [10a8129] -- Updated dependencies [c804ccc] -- Updated dependencies [5a65297] -- Updated dependencies [53406ad] -- Updated dependencies [4c5b853] -- Updated dependencies [3f3f090] -- Updated dependencies [d7a7903] -- Updated dependencies [4401a98] -- Updated dependencies [f6e9b2c] - - @google-labs/breadboard@0.11.0 - -## 0.0.5 - -### Patch Changes - -- Updated dependencies [9bcd607] -- Updated dependencies [f6a7f43] - - @google-labs/breadboard@0.10.0 - -## 0.0.4 - -### Patch Changes - -- Updated dependencies [8eccdad] -- Updated dependencies [6e8c08d] -- Updated dependencies [780909c] -- Updated dependencies [bba68fd] -- Updated dependencies [b557794] -- Updated dependencies [a9206fc] -- Updated dependencies [931a95b] - - @google-labs/breadboard@0.9.0 - -## 0.0.3 - -### Patch Changes - -- Updated dependencies [af00e58] - - @google-labs/breadboard@0.8.0 - -## [0.0.2] - 2024-01-14 - -- Update deps. - -## [0.0.1] - 2023-12-06 - -- New kit, introducing `schemish` and `validateJson` nodes. diff --git a/packages/json-kit/README.md b/packages/json-kit/README.md deleted file mode 100644 index 01228a4f332..00000000000 --- a/packages/json-kit/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Breadboard JSON Kit - -![Stability](https://img.shields.io/badge/stability-wip-green) - -A kit containing components that help wrangle JSON. - -See [docs](https://breadboard-ai.github.io/breadboard/docs/kits/json/) for the component reference. diff --git a/packages/json-kit/package.json b/packages/json-kit/package.json deleted file mode 100644 index 95c9e55e830..00000000000 --- a/packages/json-kit/package.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "name": "@google-labs/json-kit", - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "version": "0.3.8", - "description": "A Breadboard Kit containing nodes that facilitate wrangling JSON objects", - "main": "./dist/src/index.js", - "exports": "./dist/src/index.js", - "types": "dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "test": "wireit", - "test:coverage": "wireit", - "lint": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "../breadboard:build", - "../build:build", - "build:tsc" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "../breadboard:build:tsc", - "../build:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "test": { - "command": "node --test --enable-source-maps --test-reporter spec dist/tests/*.js", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "test:coverage": { - "command": "find tests -name '*.ts' | xargs c8 node --test --test-reporter=spec --loader ts-node/esm", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - } - }, - "repository": { - "directory": "packages/json-kit", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src" - ], - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard#readme", - "devDependencies": { - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "c8": "^10.1.2", - "ts-node": "^10.9.2", - "typescript": "^5.6.2" - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@google-labs/breadboard": "^0.27.0", - "@rgrove/parse-xml": "^4.1.0", - "@types/json-schema": "^7.0.15", - "ajv": "^8.17.1", - "jsonata": "^2.0.5", - "jsonschema": "^1.4.1" - } -} diff --git a/packages/json-kit/src/index.ts b/packages/json-kit/src/index.ts deleted file mode 100644 index f10c24ee78b..00000000000 --- a/packages/json-kit/src/index.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { KitBuilder } from "@google-labs/breadboard/kits"; - -import { - NewNodeFactory as NodeFactory, - NewNodeValue as NodeValue, - addKit, -} from "@google-labs/breadboard"; -import jsonata from "./nodes/jsonata.js"; -import objectToSchema from "./nodes/object-to-schema.js"; -import schemish from "./nodes/schemish.js"; -import validateJson from "./nodes/validate-json.js"; -import xmlToJson from "./nodes/xml-to-json.js"; -import { kit } from "@breadboard-ai/build"; - -export { default as jsonata } from "./nodes/jsonata.js"; - -const metadata = { - title: "JSON Kit", - description: - "A Breadboard Kit containing nodes that facilitate wrangling JSON objects", - version: "0.0.1", - url: "npm:@google-labs/json-kit", -}; - -const JSONKit = new KitBuilder(metadata).build({ - validateJson, - schemish, - jsonata, - xmlToJson, - objectToSchema, -}); - -export default JSONKit; - -export type JSONKit = InstanceType; - -export const json = addKit(JSONKit) as unknown as { - validateJson: NodeFactory< - { json: string; schema: NodeValue }, - { json: NodeValue } | { $error: NodeValue } - >; - schemish: NodeFactory<{ schema: NodeValue }, { schemish: NodeValue }>; - jsonata: NodeFactory< - | { - expression: string; - json: string; - raw: boolean; - } - | { expression: string; [key: string]: NodeValue; raw: boolean }, - { result: string } | { [key: string]: NodeValue } - >; - xmlToJson: NodeFactory<{ xml: string }, { json: NodeValue }>; - objectToSchema: NodeFactory<{ object: unknown }, { objectSchema: NodeValue }>; -}; - -export const jsonKit = await kit({ - ...metadata, - components: { jsonata, validateJson, schemish }, -}); diff --git a/packages/json-kit/src/nodes/jsonata.ts b/packages/json-kit/src/nodes/jsonata.ts deleted file mode 100644 index ead963c70df..00000000000 --- a/packages/json-kit/src/nodes/jsonata.ts +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { defineNodeType } from "@breadboard-ai/build"; -import { JsonSerializable } from "@breadboard-ai/build/internal/type-system/type.js"; -import jsonata from "jsonata"; - -export default defineNodeType({ - name: "jsonata", - metadata: { - title: "JSONata", - description: - 'Uses JSONata (a kind of "SQL for JSON") to transform incoming JSON object. See https://jsonata.org/ for details on the language.', - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/json/#the-jsonata-node", - }, - }, - inputs: { - expression: { - title: "Expression", - behavior: ["config"], - description: "The Jsonata expression to evaluate", - type: "string", - }, - raw: { - title: "Raw", - behavior: ["config"], - description: - "Whether or not to return use the evaluation result as raw output (true) or as a port called `result` (false). Default is false.", - type: "boolean", - default: false, - }, - json: { - title: "JSON", - description: - "The JSON object to evaluate. If not set, dynamically wired input ports act as the properties of a JSON object.", - type: "unknown", - optional: true, - }, - "*": { - type: "unknown", - }, - }, - outputs: { - "*": { - type: "unknown", - }, - }, - describe: async ({ expression, raw, json }, rest) => ({ - // Extra properties are allowed only if json is undefined. - inputs: json === undefined ? { "*": {} } : {}, - outputs: raw - ? // When raw, we assume that the jsonata expression returns an object, - // and update the output schema with any properties we detect on that - // object. That's not exhaustive, though, so we also still include "*" - // to indicate that there could be additional properties we didn't - // detect with the current particular value. - { ...(await detectOutputProperties(expression, json, rest)), "*": {} } - : // When not raw, the result goes to the result port, and there won't be - // any other outputs. - { - result: { - title: "Result", - description: "The result of the Jsonata expression", - }, - }, - }), - invoke: async ({ expression, raw, json }, rest) => { - if (!expression) { - // TODO(aomarks) We shouldn't need this if we ensure that invoke isn't - // called unless all required properties are set. - return { $error: "Jsonata node requires `expression` input" }; - } - // TODO(aomarks) Error if both json and rest are set. - const result: JsonSerializable = await jsonata(expression).evaluate( - json ?? rest - ); - if (raw) { - if (typeof result !== "object" || result === null) { - return { - $error: - "jsonata node in raw mode but expression did not return an object", - }; - } - return result; - } - return { result }; - }, -}); - -async function detectOutputProperties( - expression: string | undefined, - json: JsonSerializable | undefined, - rest: Record -) { - if (!expression) { - return {}; - } - let result; - try { - result = await jsonata(expression).evaluate(json ?? rest); - } catch { - return {}; - } - if (typeof result !== "object" || result === null) { - return {}; - } - return Object.fromEntries(Object.keys(result).map((name) => [name, {}])); -} diff --git a/packages/json-kit/src/nodes/object-to-schema.ts b/packages/json-kit/src/nodes/object-to-schema.ts deleted file mode 100644 index 38221ca7567..00000000000 --- a/packages/json-kit/src/nodes/object-to-schema.ts +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - InputValues, - Lambda, - NodeHandlerObject, - OutputValues, - Schema, - code, -} from "@google-labs/breadboard"; - -export function objectToSchema(obj: unknown): Schema { - if (obj === undefined) { - // Handle undefined - return {}; - } else if (obj === null) { - // Handle null - return { type: "null" }; - } else if (Array.isArray(obj)) { - // Handle arrays - const items: Schema[] = obj.map(objectToSchema); - - // Determine if all items in the array are of the same type - const allItemsSameType = items.every( - (item, _, [first]) => JSON.stringify(item) === JSON.stringify(first) - ); - - if (items.length > 0) { - // If all items are of the same type, use the first item's schema for all. - // Otherwise, set a generic items schema indicating a non-uniform array. - if (allItemsSameType) { - return { type: "array", items: items[0] }; - } else { - return { type: "array" }; - } - } - // Return a schema for an empty array if there are no items. - return { type: "array" }; - } else if (typeof obj === "object" && obj !== null) { - // Handle objects - const properties: { [key: string]: Schema } = {}; - for (const key of Object.keys(obj)) { - properties[key] = objectToSchema( - (obj as { [key: string]: unknown })[key] - ); - } - return { type: "object", properties }; - } else { - // Handle primitives - return { type: typeof obj }; - } -} - -export type ObjectToSchemaInputValues = { - object: unknown; -}; - -export type JsonSchemaOutputValues = { - objectSchema: Schema; -}; - -export const objectToSchemaCode: Lambda< - ObjectToSchemaInputValues, - JsonSchemaOutputValues -> = code(({ object }) => ({ objectSchema: objectToSchema(object) })); - -export const invoke = async (inputs: InputValues): Promise => { - if (!inputs.object) { - throw new Error("Object is required"); - } - const { object } = inputs; - return objectToSchema(object); -}; - -export const describe = async () => { - return { - inputSchema: { - properties: { - object: { - title: "Object", - description: "Any JSON object", - }, - }, - }, - outputSchema: { - properties: { - objectSchema: { - title: "Object Schema", - description: "The schema of the input object", - }, - }, - }, - }; -}; - -export default { - metadata: { - title: "Object to Schema", - description: "Creates a JSON Schema from a given object", - deprecated: true, - }, - describe, - invoke, -} as NodeHandlerObject; diff --git a/packages/json-kit/src/nodes/schemish.ts b/packages/json-kit/src/nodes/schemish.ts deleted file mode 100644 index 7ad50e6813b..00000000000 --- a/packages/json-kit/src/nodes/schemish.ts +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { defineNodeType, jsonSchema } from "@breadboard-ai/build"; -import type { NodeValue, Schema } from "@google-labs/breadboard"; - -export const convert = (schema: Schema): NodeValue => { - if (!schema.type) { - return "Any JSON object"; - } - if (schema.type === "string" || schema.type === "number") { - const result = `${schema.type}, ${schema.description}`; - const { enum: validValues } = schema; - if (validValues) { - return `${result} (one of: ${validValues - .map((value) => `"${value}"`) - .join(", ")})`; - } - return result; - } - if (schema.type === "object") { - const result: NodeValue = {}; - const properties = schema.properties as Record; - for (const [name, property] of Object.entries(properties)) { - result[name] = convert(property); - } - return result; - } - if (schema.type === "array") { - const items = (schema.items as Schema) || {}; - return [convert(items)]; - } - throw new Error( - `Failed to translate this schema to schemish:\n${JSON.stringify( - schema, - null, - 2 - )}` - ); -}; - -export default defineNodeType({ - name: "schemish", - metadata: { - title: "Schemish", - description: - "Converts a JSON schema to Schemish (https://glazkov.com/2023/05/06/schemish/)", - deprecated: true, - }, - inputs: { - schema: { - title: "schemish", - description: "The schema to convert to schemish.", - type: jsonSchema, - }, - }, - outputs: { - schemish: { - title: "schemish", - description: "The schemish object.", - type: "unknown", - }, - }, - invoke: ({ schema }) => ({ schemish: convert(schema) }), -}); diff --git a/packages/json-kit/src/nodes/validate-json.ts b/packages/json-kit/src/nodes/validate-json.ts deleted file mode 100644 index 2a56b40e40c..00000000000 --- a/packages/json-kit/src/nodes/validate-json.ts +++ /dev/null @@ -1,186 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { defineNodeType, object } from "@breadboard-ai/build"; -import { - type NodeValue, - type InputValues, - type OutputValues, - type Schema, -} from "@google-labs/breadboard"; -import Ajv from "ajv"; - -export type ValidateJsonInputs = InputValues & { - /** - * The string to validate as JSON. - */ - json: string; - /** - * Optional schema to validate against. - */ - schema?: NodeValue; - /** - * Optional boolean to enforce or turn off strict validation of the supplied schema. - */ - strictSchema?: boolean; -}; - -export type ValidationErrorType = "parsing" | "schema" | "validation"; - -export type InvalidJsonOutputs = OutputValues & { - /** - * The error if the JSON is invalid. - */ - $error: { - kind: "error"; - error: { - /** - * The type of error. - */ - type: ValidationErrorType; - /** - * The message of the error. - */ - message: string; - }; - }; -}; - -export type ValidatedJsonOutputs = OutputValues & { - /** - * The validated JSON. - */ - json: NodeValue; -}; - -export type ValidateJsonOutputs = InvalidJsonOutputs | ValidatedJsonOutputs; - -export const stripCodeBlock = (code: string) => - code.replace(/(?:.*)(?:```(?:json)?\n+)(.*)(?:\n+```)(?:.*)/gms, "$1"); - -export const tryParseJson = (json: string): InvalidJsonOutputs | NodeValue => { - try { - return JSON.parse(stripCodeBlock(json)); - } catch (e) { - const error = e as Error; - return { - $error: { - kind: "error", - error: { type: "parsing", message: error.message }, - }, - }; - } -}; - -export const validateJson = ( - parsed: NodeValue, - schema: Schema, - strictSchema: boolean | undefined = undefined -): ValidateJsonOutputs => { - const result = { json: parsed }; - if (!schema) return result; - const validator = new Ajv.default({ strict: strictSchema }); - let validate: Ajv.ValidateFunction; - try { - validate = validator.compile(schema); - } catch (e) { - return { - $error: { - kind: "error", - error: { - type: "schema", - message: (e as Error).message, - }, - }, - }; - } - - const valid = validate(parsed); - if (!valid) { - return { - $error: { - kind: "error", - error: { - type: "validation", - message: validator.errorsText(validate.errors), - }, - }, - }; - } - - return result; -}; - -const invoke = async (inputs: InputValues): Promise => { - const { json, schema, strictSchema } = inputs as ValidateJsonInputs; - if (!json) throw new Error("The `json` input is required."); - - if (!schema && strictSchema == true) { - throw new Error( - "The `schema` input is required when `strictSchema` is true." - ); - } - - // First, let's try to parse JSON. - const parsed = tryParseJson(json); - const possiblyInvalid = parsed as InvalidJsonOutputs; - if (possiblyInvalid?.$error) return possiblyInvalid; - - // Then, let's make sure we have schema in the right format. - let parsedSchema = schema; - if (schema && typeof schema === "string") { - try { - parsedSchema = tryParseJson(schema); - } catch (e) { - throw new Error("The `schema` input is not valid JSON."); - } - } - - // Now, let's try to validate JSON. - return validateJson(parsed, parsedSchema as Schema, strictSchema); -}; - -export default defineNodeType({ - name: "validateJson", - metadata: { - title: "Validate JSON", - description: - "Validates given text as JSON, trying its best to parse it first.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/json/#validatejson", - }, - }, - inputs: { - json: { - title: "JSON string", - description: "The string to validate as JSON.", - type: "string", - }, - schema: { - title: "Schema", - description: "Optional schema to validate against.", - type: object({}, "unknown"), - behavior: ["config"], - optional: true, - }, - strictSchema: { - title: "Strict", - description: - "Optional boolean to enforce or turn off strict validation of the supplied schema.", - type: "boolean", - behavior: ["config"], - default: false, - }, - }, - outputs: { - json: { - title: "JSON", - description: "The validated JSON.", - type: "unknown", - }, - }, - invoke, -}); diff --git a/packages/json-kit/src/nodes/xml-to-json.ts b/packages/json-kit/src/nodes/xml-to-json.ts deleted file mode 100644 index cf0e9bacea2..00000000000 --- a/packages/json-kit/src/nodes/xml-to-json.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - InputValues, - NodeHandler, - NodeValue, - OutputValues, -} from "@google-labs/breadboard"; -import { - XmlCdata, - XmlComment, - XmlDocument, - XmlElement, - XmlText, - parseXml, -} from "@rgrove/parse-xml"; - -export type XmlToJsonOutputs = { - json: unknown; -}; - -export type XmlToJsonInputs = { - /** - * The string that contains the XML to convert to JSON - * @example `baz` - */ - xml: string; -}; - -const properName = (name: string) => { - return name.replace(/:/g, "$"); -}; - -/** - * Converts to alt-json format, as outlined in: - * https://developers.google.com/gdata/docs/json - * @param node - * @returns - */ -const toAltJson = ( - node: XmlElement | XmlDocument | XmlText | XmlCdata | XmlComment -): [string, NodeValue] => { - if (node.type === "document") { - const doc = node as XmlDocument; - const element = doc.children.find( - (child) => child.type === "element" - ) as XmlElement; - const [name, value] = toAltJson(element); - return ["$doc", element ? { [name]: value } : ""]; - } - if (node.type === "element") { - const element = node as XmlElement; - const childEntries = element.children.map(toAltJson) as [string, unknown][]; - const children = Object.fromEntries( - childEntries.reduce((map, [name, value]) => { - map.has(name) ? map.get(name).push(value) : map.set(name, [value]); - return map; - }, new Map()) - ); - return [properName(element.name), { ...children, ...element.attributes }]; - } - if (node.type === "text") { - const text = node as XmlText; - return ["$t", text.text]; - } - return ["$c", ""]; -}; - -export default { - metadata: { - title: "XML to JSON", - description: "Creates a JSON representation of a given XML input.", - help: { - url: "https://breadboard-ai.github.io/breadboard/docs/kits/json/#the-xmltojson-node", - }, - }, - describe: async () => { - return { - inputSchema: { - properties: { - xml: { - title: "XML String", - type: "string", - description: "Valid XML as a string", - }, - }, - }, - outputSchema: { - properties: { - json: { - title: "JSON", - type: "object", - description: - "JSON representation of the input XML. Represented as alt-json, described in https://developers.google.com/gdata/docs/json", - }, - }, - }, - }; - }, - invoke: async (inputs: InputValues): Promise => { - const { xml } = inputs as XmlToJsonInputs; - if (!xml) throw new Error("XmlToJson requires `xml` input"); - const json = toAltJson(parseXml(xml)); - return { json }; - }, -} satisfies NodeHandler; diff --git a/packages/json-kit/tests/jsonata.ts b/packages/json-kit/tests/jsonata.ts deleted file mode 100644 index 8eabe30dd41..00000000000 --- a/packages/json-kit/tests/jsonata.ts +++ /dev/null @@ -1,214 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import test, { describe } from "node:test"; -import jsonata from "../src/nodes/jsonata.js"; - -describe("jsonata", () => { - test("`jsonata.describe` correctly reacts to `raw = `", async () => { - const result = await jsonata.describe(); - const expected = { - inputSchema: { - type: "object", - properties: { - expression: { - title: "Expression", - behavior: ["config"], - description: "The Jsonata expression to evaluate", - type: "string", - }, - raw: { - title: "Raw", - behavior: ["config"], - description: - "Whether or not to return use the evaluation result as raw output (true) or as a port called `result` (false). Default is false.", - type: "boolean", - default: false, - }, - json: { - title: "JSON", - description: - "The JSON object to evaluate. If not set, dynamically wired input ports act as the properties of a JSON object.", - type: ["array", "boolean", "null", "number", "object", "string"], - }, - }, - additionalProperties: true, - required: ["expression"], - }, - outputSchema: { - type: "object", - properties: { - result: { - title: "Result", - description: "The result of the Jsonata expression", - type: ["array", "boolean", "null", "number", "object", "string"], - }, - }, - required: [], - additionalProperties: false, - }, - }; - assert.deepEqual(result, expected); - }); - - test("`jsonata.describe` correctly reacts to `raw = true`", async () => { - const result = await jsonata.describe({ - expression: "foo", - json: { foo: { bar: "baz" } }, - raw: true, - }); - const expected = { - inputSchema: { - type: "object", - properties: { - expression: { - title: "Expression", - behavior: ["config"], - description: "The Jsonata expression to evaluate", - type: "string", - }, - raw: { - title: "Raw", - behavior: ["config"], - description: - "Whether or not to return use the evaluation result as raw output (true) or as a port called `result` (false). Default is false.", - type: "boolean", - default: false, - }, - json: { - title: "JSON", - description: - "The JSON object to evaluate. If not set, dynamically wired input ports act as the properties of a JSON object.", - type: ["array", "boolean", "null", "number", "object", "string"], - }, - }, - additionalProperties: false, - required: ["expression"], - }, - outputSchema: { - type: "object", - properties: { - bar: { - type: ["array", "boolean", "null", "number", "object", "string"], - title: "bar", - }, - }, - required: [], - additionalProperties: true, - }, - }; - assert.deepEqual(result, expected); - }); - - test("`jsonata.describe` correctly reacts to invalid input", async () => { - const result = await jsonata.describe({ - raw: true, - }); - const expected = { - inputSchema: { - type: "object", - properties: { - expression: { - title: "Expression", - behavior: ["config"], - description: "The Jsonata expression to evaluate", - type: "string", - }, - raw: { - title: "Raw", - behavior: ["config"], - description: - "Whether or not to return use the evaluation result as raw output (true) or as a port called `result` (false). Default is false.", - type: "boolean", - default: false, - }, - json: { - title: "JSON", - description: - "The JSON object to evaluate. If not set, dynamically wired input ports act as the properties of a JSON object.", - type: ["array", "boolean", "null", "number", "object", "string"], - }, - }, - additionalProperties: true, - required: ["expression"], - }, - outputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - }, - }; - assert.deepEqual(result, expected); - }); - - test("invoke in raw mode", async () => { - const actual = await jsonata.invoke( - { - raw: true, - expression: "foo", - json: { foo: { bar: "baz" } }, - }, - null as never - ); - const expected = { - bar: "baz", - }; - assert.deepEqual(actual, expected); - }); - - test("invoke in not raw mode", async () => { - const actual = await jsonata.invoke( - { - expression: "foo", - json: { foo: { bar: "baz" } }, - }, - null as never - ); - const expected = { - result: { - bar: "baz", - }, - }; - assert.deepEqual(actual, expected); - }); - - test("invoke in not raw mode and doesn't return object", async () => { - assert.deepEqual( - await jsonata.invoke( - { - expression: "foo.bar", - json: { foo: { bar: "baz" } }, - }, - null as never - ), - { result: "baz" } - ); - }); - - test("invoke in raw mode and doesn't return object", async () => { - assert.deepEqual( - await jsonata.invoke( - { - raw: true, - expression: "foo.bar", - json: { foo: { bar: "baz" } }, - }, - null as never - ), - { - $error: { - kind: "error", - error: { - message: - "jsonata node in raw mode but expression did not return an object", - }, - }, - } - ); - }); -}); diff --git a/packages/json-kit/tests/object-to-schema.ts b/packages/json-kit/tests/object-to-schema.ts deleted file mode 100644 index bc55260e57a..00000000000 --- a/packages/json-kit/tests/object-to-schema.ts +++ /dev/null @@ -1,170 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Schema } from "ajv"; -import assert from "node:assert"; -import test, { describe } from "node:test"; -import { - objectToSchema, - objectToSchemaCode, -} from "../src/nodes/object-to-schema.js"; - -describe("objectToSchema", () => { - test("should convert an array to a schema", () => { - const obj = [1, 2, 3]; - const actual: Schema = objectToSchema(obj); - const expected: Schema = { - type: "array", - items: { type: "number" }, - }; - assert.deepStrictEqual(actual, expected); - }); - - test("should convert an array of objects to a schema", () => { - const obj = [ - { name: "John", age: 30 }, - { name: "Jane", age: 25 }, - ]; - const actual: Schema = objectToSchema(obj); - const expected: Schema = { - type: "array", - items: { - type: "object", - properties: { - name: { type: "string" }, - age: { type: "number" }, - }, - }, - }; - assert.deepStrictEqual(actual, expected); - }); - - test("should convert an array of arrays to a schema", () => { - const obj = [ - [1, 2], - [3, 4], - ]; - const schema: Schema = objectToSchema(obj); - const expected: Schema = { - type: "array", - items: { - type: "array", - items: { - type: "number", - }, - }, - }; - assert.deepStrictEqual(schema, expected); - }); - - test("should convert an empty array to a schema", () => { - const obj: [] = []; - const actual: Schema = objectToSchema(obj); - const expected: Schema = { type: "array" }; - assert.deepStrictEqual(actual, expected); - }); - - test("should convert an array of mixed types to a schema", () => { - const obj: (string | boolean | number)[] = [1, "Hello, world!", true]; - const actual: Schema = objectToSchema(obj); - const expected: Schema = { - type: "array", - }; - assert.deepStrictEqual(actual, expected); - }); - - test("should convert an object to a schema", () => { - const obj = { name: "John", age: 30 }; - const actual: Schema = objectToSchema(obj); - const expected: Schema = { - type: "object", - properties: { - name: { type: "string" }, - age: { type: "number" }, - }, - }; - assert.deepStrictEqual(actual, expected); - }); - - test("should convert a primitive value to a schema", () => { - const obj = "Hello, world!"; - const actual: Schema = objectToSchema(obj); - const expected: Schema = { type: "string" }; - assert.deepStrictEqual(actual, expected); - }); - - test("should convert a null value to a schema", () => { - const obj = null; - const actual: Schema = objectToSchema(obj); - const expected: Schema = { type: "null" }; - assert.deepStrictEqual(actual, expected); - }); - - test("should convert an undefined value to a schema", () => { - const obj = undefined; - const actual: Schema = objectToSchema(obj); - const expected: Schema = {}; - assert.deepStrictEqual(actual, expected); - }); - - test("should convert a boolean value to a schema", () => { - const obj = true; - const actual: Schema = objectToSchema(obj); - const expected: Schema = { type: "boolean" }; - assert.deepStrictEqual(actual, expected); - }); - - test("should convert a number value to a schema", () => { - const obj = 42; - const actual: Schema = objectToSchema(obj); - const expected: Schema = { type: "number" }; - assert.deepStrictEqual(actual, expected); - }); - - test("should convert an object with no properties to a schema", () => { - const obj = {}; - const actual: Schema = objectToSchema(obj); - const expected: Schema = { type: "object", properties: {} }; - assert.deepStrictEqual(actual, expected); - }); - - test("should convert an instance of a class to a schema", () => { - class Person { - constructor( - public name: string, - public age: number - ) {} - } - - const obj = new Person("John", 30); - const actual: Schema = objectToSchema(obj); - const expected: Schema = { - type: "object", - properties: { - name: { type: "string" }, - age: { type: "number" }, - }, - }; - assert.deepStrictEqual(actual, expected); - }); - test("code node executes as expected", async () => { - const input = { name: "John", age: 30 }; - const result = (await objectToSchemaCode().invoke({ - object: input, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - })) as any; - assert(result.objectSchema); - const actual = result.objectSchema; - const expected: Schema = { - type: "object", - properties: { - name: { type: "string" }, - age: { type: "number" }, - }, - }; - assert.deepStrictEqual(actual, expected); - }); -}); diff --git a/packages/json-kit/tests/schemish.ts b/packages/json-kit/tests/schemish.ts deleted file mode 100644 index e80d8bae684..00000000000 --- a/packages/json-kit/tests/schemish.ts +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { deepStrictEqual } from "node:assert"; -import test, { describe } from "node:test"; -import { convert } from "../src/nodes/schemish.js"; - -describe("schemish", () => { - test("converts a simple schema", (t) => { - const schema = { - type: "object", - properties: { - name: { type: "string", description: "The name of the person." }, - }, - }; - const result = convert(schema); - deepStrictEqual(result, { name: "string, The name of the person." }); - }); - - test("converts a schema with strings and numbers", (t) => { - const schema = { - type: "object", - properties: { - name: { type: "string", description: "The name of the person." }, - age: { type: "number", description: "The age of the person." }, - }, - }; - const result = convert(schema); - deepStrictEqual(result, { - name: "string, The name of the person.", - age: "number, The age of the person.", - }); - }); - - test("converts a schema with nested objects", (t) => { - const schema = { - type: "object", - properties: { - name: { type: "string", description: "The name of the person." }, - age: { type: "number", description: "The age of the person." }, - address: { - type: "object", - properties: { - street: { type: "string", description: "The street address." }, - city: { type: "string", description: "The city address." }, - }, - }, - }, - }; - const result = convert(schema); - deepStrictEqual(result, { - name: "string, The name of the person.", - age: "number, The age of the person.", - address: { - street: "string, The street address.", - city: "string, The city address.", - }, - }); - }); - - test("converts a schema with arrays", (t) => { - const schema = { - type: "object", - properties: { - name: { type: "string", description: "The name of the person." }, - age: { type: "number", description: "The age of the person." }, - favoriteNumbers: { - type: "array", - items: { type: "number", description: "A favorite number." }, - }, - }, - }; - const result = convert(schema); - deepStrictEqual(result, { - name: "string, The name of the person.", - age: "number, The age of the person.", - favoriteNumbers: ["number, A favorite number."], - }); - }); - - test("converts a schema with enums", (t) => { - const schema = { - type: "string", - description: "The type of order.", - enum: ["drink", "food"], - }; - const result = convert(schema); - deepStrictEqual( - result, - `string, The type of order. (one of: "drink", "food")` - ); - }); - - test("can handle an empty schema", (t) => { - const schema = {}; - const result = convert(schema); - deepStrictEqual(result, "Any JSON object"); - }); -}); diff --git a/packages/json-kit/tests/validate-json.ts b/packages/json-kit/tests/validate-json.ts deleted file mode 100644 index d905f95e586..00000000000 --- a/packages/json-kit/tests/validate-json.ts +++ /dev/null @@ -1,161 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { deepStrictEqual } from "node:assert"; -import test, { describe } from "node:test"; -import { - stripCodeBlock, - tryParseJson, - validateJson, -} from "../src/nodes/validate-json.js"; - -describe("validate-json", () => { - test("tryParseJson correctly parses JSON", (t) => { - const json = `{"foo": "bar"}`; - const result = tryParseJson(json); - deepStrictEqual(result, { foo: "bar" }); - }); - - test("tryParseJson correctly returns an error for unparsable JSON", (t) => { - const json = `{"foo": bar}`; - const result = tryParseJson(json); - deepStrictEqual(result, { - $error: { - kind: "error", - error: { - type: "parsing", - message: 'Unexpected token \'b\', "{"foo": bar}" is not valid JSON', - }, - }, - }); - }); - - test("validateJson correctly validates JSON", (t) => { - const parsed = { foo: "bar" }; - const schema = { - type: "object", - properties: { foo: { type: "string" } }, - }; - const result = validateJson(parsed, schema); - deepStrictEqual(result, { json: { foo: "bar" } }); - }); - - test("validateJson correctly returns an error for invalid JSON", (t) => { - const parsed = { foo: "bar" }; - const schema = { - type: "object", - properties: { foo: { type: "number" } }, - }; - const result = validateJson(parsed, schema); - deepStrictEqual(result, { - $error: { - kind: "error", - error: { - type: "validation", - message: "data/foo must be number", - }, - }, - }); - }); - - test("validateJson fails when strictSchema is true and the schema is invalid", (t) => { - const parsed = { foo: 1 }; - const schema = { - type: "object", - properties: { foo: { type: "number", example: "Test" } }, // Using "example" because the OpenAI OpenAPI schema uses it - }; - const result = validateJson(parsed, schema, true); - deepStrictEqual(result, { - $error: { - kind: "error", - error: { - type: "schema", - message: 'strict mode: unknown keyword: "example"', - }, - }, - }); - }); - - test("validateJson passes when strictSchema is true and the schema is valid", (t) => { - const parsed = { foo: 1 }; - const schema = { - type: "object", - properties: { foo: { type: "number" } }, // Using "example" because the OpenAI OpenAPI schema uses it - }; - const result = validateJson(parsed, schema, true); - deepStrictEqual(result, { - json: { foo: 1 }, - }); - }); - - test("validateJson fails when strictSchema is undefined and the schema is invalid", (t) => { - const parsed = { foo: 1 }; - const schema = { - type: "object", - properties: { foo: { type: "number", example: "Test" } }, - }; - const result = validateJson(parsed, schema); - deepStrictEqual(result, { - $error: { - kind: "error", - error: { - type: "schema", - message: 'strict mode: unknown keyword: "example"', - }, - }, - }); - }); - - test("validateJson passes when strictSchema is undefined and the schema is valid", (t) => { - const parsed = { foo: 1 }; - const schema = { - type: "object", - properties: { foo: { type: "number" } }, - }; - const result = validateJson(parsed, schema); - deepStrictEqual(result, { - json: { foo: 1 }, - }); - }); - - test("validateJson passes when strictSchema is false and the schema is invalid", (t) => { - const parsed = { foo: 1 }; - const schema = { - type: "object", - properties: { foo: { type: "number", example: "Test" } }, - }; - const result = validateJson(parsed, schema, false); - deepStrictEqual(result, { - json: { foo: 1 }, - }); - }); - - test("stripCodeBlock correctly strips Markdown only if present", (t) => { - deepStrictEqual(stripCodeBlock('```json\n"json"\n```'), '"json"'); - deepStrictEqual(stripCodeBlock('```\n"json"\n```'), '"json"'); - deepStrictEqual(stripCodeBlock('"json"'), '"json"'); - }); - - test("tryParseJson correctly parses JSON with Markdown code block", (t) => { - const json = '```json\n{"foo": "bar"}\n```'; - const result = tryParseJson(json); - deepStrictEqual(result, { foo: "bar" }); - }); - - test("tryParseJson correctly strips stuff outside of the Markdown code block", (t) => { - { - const json = 'bar```json\n{"foo": "bar"}\n```\nfooo'; - const result = tryParseJson(json); - deepStrictEqual(result, { foo: "bar" }); - } - { - const json = - 'sure, here is the JSON you requested:\n\n```json\n{"foo": "bar"}\n```\n\nAdditionally, here is an alternative version of this JSON:\n\n```json\n{"bar": "baz"}\n```\n\nI hope this helps!'; - const result = tryParseJson(json); - deepStrictEqual(result, { bar: "baz" }); - } - }); -}); diff --git a/packages/json-kit/tests/xml-to-json.ts b/packages/json-kit/tests/xml-to-json.ts deleted file mode 100644 index 6c2bf046b39..00000000000 --- a/packages/json-kit/tests/xml-to-json.ts +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { deepEqual } from "node:assert"; -import test, { describe } from "node:test"; -import xmlToJson from "../src/nodes/xml-to-json.js"; -describe("xml-to-json", () => { - test("xml-to-json can parse documents without processing instructions", async () => { - const xml = `baz`; - const expectedJson = { - json: ["$doc", { foo: { bar: [{ $t: ["baz"] }] } }], - }; - - const json = await xmlToJson.invoke({ xml }); - deepEqual(json, expectedJson); - }); - - test("xml-to-json can parse documents with processing instructions", async () => { - const xml = `baz`; - const expectedJson = { - json: ["$doc", { foo: { bar: [{ $t: ["baz"] }] } }], - }; - - const json = await xmlToJson.invoke({ xml }); - deepEqual(json, expectedJson); - }); - - test("xml-to-json can parse documents with two processing instructions", async () => { - const xml = `baz`; - const expectedJson = { - json: ["$doc", { foo: { bar: [{ $t: ["baz"] }] } }], - }; - - const json = await xmlToJson.invoke({ xml }); - deepEqual(json, expectedJson); - }); -}); diff --git a/packages/json-kit/tsconfig.json b/packages/json-kit/tsconfig.json deleted file mode 100644 index 1ff943cd641..00000000000 --- a/packages/json-kit/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "outDir": "./dist" - }, - "include": ["src/**/*", "tests/**/*"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/manifest/CHANGELOG.md b/packages/manifest/CHANGELOG.md deleted file mode 100644 index e04201262a5..00000000000 --- a/packages/manifest/CHANGELOG.md +++ /dev/null @@ -1,173 +0,0 @@ -# @google-labs/breadboard-manifest - -## 0.4.4 - -### Patch Changes - -- Updated dependencies [703f17d] -- Updated dependencies [8d06f3c] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [4dadf16] -- Updated dependencies [8f9fddf] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [9797718] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [a039d2e] -- Updated dependencies [9783ba8] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [d7606d3] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] - - @google-labs/breadboard@0.27.0 - - @google-labs/breadboard-schema@1.8.0 - -## 0.4.3 - -### Patch Changes - -- Updated dependencies [7d46a63] - - @google-labs/breadboard@0.26.0 - -## 0.4.2 - -### Patch Changes - -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @google-labs/breadboard@0.25.0 - - @google-labs/breadboard-schema@1.7.0 - -## 0.4.1 - -### Patch Changes - -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [1dc645a] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [c04cff0] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - -## 0.4.0 - -### Minor Changes - -- 5f6d97c: Separate playground and examples - -### Patch Changes - -- Updated dependencies [1e1be2a] -- Updated dependencies [2b094a3] -- Updated dependencies [fa93c3f] -- Updated dependencies [215bd15] -- Updated dependencies [2b9ef5b] -- Updated dependencies [a0852df] -- Updated dependencies [2312443] -- Updated dependencies [6ffa89c] - - @google-labs/breadboard@0.23.0 - - @google-labs/breadboard-schema@1.6.0 - -## 0.3.0 - -### Minor Changes - -- bc8dcdd: rework manifest package - -### Patch Changes - -- 4da35e5: Fix unit tests. -- Updated dependencies [a925cf0] -- Updated dependencies [dd783e0] -- Updated dependencies [5cf08f1] -- Updated dependencies [ffbf163] -- Updated dependencies [8928fb7] -- Updated dependencies [d6706f2] -- Updated dependencies [5447426] -- Updated dependencies [3aba1a4] -- Updated dependencies [7e1f01c] - - @google-labs/breadboard@0.22.0 - - @google-labs/breadboard-schema@1.5.1 - -## 0.2.0 - -### Minor Changes - -- 1f7e37d: updates for breadboard web - -### Patch Changes - -- 537d9f9: Add guide on creating tools -- Updated dependencies [5a55b7d] -- Updated dependencies [74ade20] -- Updated dependencies [59dd0f5] -- Updated dependencies [417323c] -- Updated dependencies [b3aa884] -- Updated dependencies [3d7b4a7] -- Updated dependencies [7af14cf] -- Updated dependencies [fea8967] -- Updated dependencies [778f7aa] -- Updated dependencies [808f5e2] -- Updated dependencies [511bd9b] -- Updated dependencies [e0fdbc3] -- Updated dependencies [54b03b9] -- Updated dependencies [810d7fd] -- Updated dependencies [14853d5] -- Updated dependencies [8798514] -- Updated dependencies [eb64b9a] -- Updated dependencies [431fa3d] -- Updated dependencies [32a48a3] -- Updated dependencies [cd73b17] -- Updated dependencies [81d82fe] -- Updated dependencies [2a7531b] -- Updated dependencies [7c1b4cb] -- Updated dependencies [702cfe1] -- Updated dependencies [bebd96e] -- Updated dependencies [91cb723] -- Updated dependencies [3e10f0f] -- Updated dependencies [c53ca01] -- Updated dependencies [4c681cb] -- Updated dependencies [fb2e584] -- Updated dependencies [9491266] -- Updated dependencies [2ace620] -- Updated dependencies [fcef799] -- Updated dependencies [37418d9] -- Updated dependencies [083f69c] -- Updated dependencies [5b03d96] -- Updated dependencies [f0d8d67] -- Updated dependencies [836389d] -- Updated dependencies [225c7cc] - - @google-labs/breadboard@0.21.0 - - @google-labs/breadboard-schema@1.5.0 diff --git a/packages/manifest/README.md b/packages/manifest/README.md deleted file mode 100644 index 49c75c4ced0..00000000000 --- a/packages/manifest/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Breadboard Manifest - -A tool that generates a manifest of board files. diff --git a/packages/manifest/bbm.schema.json b/packages/manifest/bbm.schema.json deleted file mode 100644 index a424682e6ed..00000000000 --- a/packages/manifest/bbm.schema.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "$id": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@breadboard-ai/manifest@0.4.4/packages/manifest/bbm.schema.json", - "$ref": "#/definitions/BreadboardManifest", - "$schema": "http://json-schema.org/draft-07/schema#", - "definitions": { - "Board": { - "$ref": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.8.0/packages/schema/breadboard.schema.json#/definitions/GraphDescriptor", - "description": "A reference to the BGL schema GraphDescriptor type.", - "type": "object" - }, - "BoardReference": { - "anyOf": [ - { - "$ref": "#/definitions/ResourceReference" - }, - { - "$ref": "#/definitions/Board" - } - ], - "description": "Union of {@link ResourceReference } and {@link Board }" - }, - "BreadboardManifest": { - "additionalProperties": false, - "description": "A Breadboard Manifest.\n\nContains references to boards and other manifests.", - "examples": [ - { - "title": "Empty Manifest" - }, - { - "boards": [], - "manifests": [], - "title": "Manifest with empty lists" - }, - { - "boards": [ - { - "title": "My First Board", - "url": "https://gist.githubusercontent.com/user/SOME_ID/raw/board.bgl.json", - "version": "1.0.0" - }, - { - "title": "My Second Board", - "url": "./boards/board.bgl.json" - } - ], - "manifests": [ - { - "title": "Gist Manifest", - "url": "https://gist.githubusercontent.com/user/SOME_ID/raw/manifest.bbm.json" - } - ] - }, - { - "boards": [ - { - "edges": [], - "nodes": [], - "title": "My First Board" - } - ], - "title": "Manifest with concrete boards" - } - ], - "properties": { - "$schema": { - "$ref": "#/definitions/Reference" - }, - "boards": { - "items": { - "$ref": "#/definitions/BoardReference" - }, - "type": "array" - }, - "manifests": { - "items": { - "$ref": "#/definitions/ManifestReference" - }, - "type": "array" - }, - "reference": { - "$ref": "#/definitions/Reference" - }, - "tags": { - "$ref": "#/definitions/Tags" - }, - "title": { - "$ref": "#/definitions/Title" - } - }, - "type": "object" - }, - "ManifestReference": { - "anyOf": [ - { - "$ref": "#/definitions/ResourceReference" - }, - { - "$ref": "#/definitions/BreadboardManifest" - } - ], - "description": "Union of {@link ResourceReference } and {@link BreadboardManifest }" - }, - "Reference": { - "anyOf": [ - { - "$ref": "#/definitions/UriReference" - }, - { - "$ref": "#/definitions/RelativeReference" - } - ], - "description": "A reference to a resource." - }, - "RelativeReference": { - "description": "A reference to a resource relative to the Uri of the parent resource.", - "examples": [ - "../boards/board.bgl.json", - "../manifests/manifest.bbm.json", - "./board.bgl.json", - "./manifest.bbm.json", - "board.bgl.json", - "manifest.bbm.json" - ], - "pattern": "^(\\.\\/|\\.\\.\\/|[a-zA-Z0-9_.-]+\\/)*[a-zA-Z0-9_.-]+$", - "type": "string" - }, - "ResourceReference": { - "additionalProperties": false, - "description": "A resource that definitely has a reference.\n\nAlso has a title.", - "properties": { - "reference": { - "$ref": "#/definitions/Reference" - }, - "tags": { - "$ref": "#/definitions/Tags" - }, - "title": { - "$ref": "#/definitions/Title" - } - }, - "required": [ - "reference" - ], - "type": "object" - }, - "Tags": { - "description": "The tags for this board", - "items": { - "type": "string" - }, - "type": "array" - }, - "Title": { - "examples": [ - "Gist Manifest", - "My First Board" - ], - "type": "string" - }, - "UriReference": { - "description": "A URI reference.", - "examples": [ - "file:///path/to/board.bgl.json", - "file:///path/to/manifest.bbm.json", - "https://example.com/board.bgl.json", - "https://example.com/manifest.bbm.json", - "https://example.com/manifests/manifest.bbm.json" - ], - "format": "uri-reference", - "type": "string" - } - } -} \ No newline at end of file diff --git a/packages/manifest/package.json b/packages/manifest/package.json deleted file mode 100644 index 0a0f82f027d..00000000000 --- a/packages/manifest/package.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "author": "Google Labs Team", - "dependencies": { - "@google-labs/breadboard": "^0.27.0", - "@google-labs/breadboard-schema": "^1.8.0" - }, - "devDependencies": { - "@types/node": "^22.0.0", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "ajv-keywords": "^5.1.0", - "c8": "^10.1.2", - "ts-json-schema-generator": "^2.3.0", - "tsx": "^4.19.1", - "typescript": "^5.6.2" - }, - "exports": { - ".": "./dist/index.js", - "./*": [ - "./dist/*" - ], - "./bbm.schema.json": "./bbm.schema.json" - }, - "files": [ - "**/*.ts", - "dist/**/*.js", - "dist/**/*.js.map", - "dist/**/*.d.ts.map", - "./bbm.schema.json", - "./package.json" - ], - "license": "Apache-2.0", - "name": "@breadboard-ai/manifest", - "repository": { - "directory": "packages/manifest", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "scripts": { - "build": "wireit", - "build:schema": "wireit", - "build:ts": "wireit", - "build:verbose": "WIREIT_LOGGER=metrics npm run build", - "test": "wireit", - "test:verbose": "WIREIT_LOGGER=metrics npm run test", - "validate": "wireit" - }, - "type": "module", - "version": "0.4.4", - "wireit": { - "build": { - "dependencies": [ - "build:schema", - "build:ts" - ] - }, - "build:schema": { - "command": "tsx --no-cache ./src/scripts/generate.ts", - "dependencies": [ - "../breadboard:build", - "../schema:build", - "validate" - ], - "files": [ - "src/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "bbm.schema.json" - ] - }, - "build:ts": { - "command": "tsc -b -v --pretty", - "clean": "if-file-deleted", - "files": [ - "src/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/**", - "tsconfig.tsbuildinfo" - ], - "dependencies": [ - "build:schema", - "../breadboard:build", - "../schema:build" - ] - }, - "test": { - "command:disabled": "c8 node --import tsx --test-reporter spec --test src/tests/index.test.ts ", - "command": "echo TEST TEMPORARILY DISABLED", - "dependencies": [ - "build:schema" - ], - "files": [], - "output": [], - "env": { - "FORCE_COLOR": "1" - } - }, - "validate": { - "command": "tsc --noEmit --skipLibCheck", - "dependencies": [ - "../breadboard:build", - "../schema:build" - ], - "files": [ - "src/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [] - } - } -} diff --git a/packages/manifest/src/index.ts b/packages/manifest/src/index.ts deleted file mode 100644 index 408dcfbb46b..00000000000 --- a/packages/manifest/src/index.ts +++ /dev/null @@ -1,201 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { GraphDescriptor } from "@google-labs/breadboard"; - -/** - * A Breadboard Manifest. - * - * Contains references to boards and other manifests. - * - * @examples [ - * { - * "title": "Empty Manifest" - * }, - * { - * "title": "Manifest with empty lists", - * "boards": [], - * "manifests": [] - * }, - * { - * "boards": [ - * { - * "title": "My First Board", - * "url": "https://gist.githubusercontent.com/user/SOME_ID/raw/board.bgl.json", - * "version": "1.0.0" - * }, - * { - * "title": "My Second Board", - * "url": "./boards/board.bgl.json" - * } - * ], - * "manifests": [ - * { - * "title": "Gist Manifest", - * "url": "https://gist.githubusercontent.com/user/SOME_ID/raw/manifest.bbm.json" - * } - * ] - * }, - * { - * "title": "Manifest with concrete boards", - * "boards": [ - * { - * "title": "My First Board", - * "nodes": [], - * "edges": [] - * } - * ] - * } - * ] - */ -export interface BreadboardManifest extends Resource { - $schema?: Reference; - boards?: BoardReference[]; - manifests?: ManifestReference[]; - reference?: Reference; - title?: Title; - tags?: Tags; -} - -export class BreadboardManifestBuilder implements BreadboardManifest { - readonly $schema?: Reference; - boards?: BoardReference[]; - readonly reference?: Reference; - manifests?: ManifestReference[]; - title?: Title; - tags?: Tags; - - constructor(manifest: BreadboardManifest = {}) { - this.$schema = manifest.$schema; - this.boards = manifest.boards; - this.manifests = manifest.manifests; - this.reference = manifest.reference; - this.title = manifest.title; - this.tags = manifest.tags; - } - - addBoard(board: BoardReference): void { - if (!this.boards) { - this.boards = []; - } - this.boards.push(board); - } - - addboards(boards: BoardReference[]): void { - boards.forEach(this.addBoard); - } - - addManifest(manifest: ManifestReference): void { - if (!this.manifests) { - this.manifests = []; - } - this.manifests.push(manifest); - } - - addManifests(manifests: ManifestReference[]): void { - manifests.forEach(this.addManifest); - } -} - -export { isReference } from "./isReference"; - -/** - * A URI reference. - * - * @format uri-reference - * - * @examples [ - * "https://example.com/board.bgl.json", - * "https://example.com/manifest.bbm.json", - * "https://example.com/manifests/manifest.bbm.json", - * "file:///path/to/board.bgl.json", - * "file:///path/to/manifest.bbm.json" - * ] - */ -export type UriReference = string; - -/** - * A reference to a resource relative to the Uri of the parent resource. - * - * @pattern ^(\.\/|\.\.\/|[a-zA-Z0-9_.-]+\/)*[a-zA-Z0-9_.-]+$ - * - * @examples [ - * "board.bgl.json", - * "manifest.bbm.json", - * "../boards/board.bgl.json", - * "../manifests/manifest.bbm.json", - * "./board.bgl.json", - * "./manifest.bbm.json" - * ] - */ -export type RelativeReference = string; - -/** - * A reference to a resource. - */ -export type Reference = UriReference | RelativeReference; - -/** - * A resource that definitely has a reference. - * - * Also has a title. - */ -export interface ResourceReference extends Resource { - readonly reference: Reference; - readonly title?: Title; - readonly tags?: Tags; -} - -/** - * A referenceable resource. - */ -export interface Resource { - reference?: Reference; -} - -/** - * Allow additional properties. - */ -export type AdditionalProperties = { - [x: string | number | symbol]: unknown; -}; - -/** - * A Resource that allows additional properties. - */ -export interface ResourceWithAdditionalProperties - extends Resource, - AdditionalProperties {} - -/** - * A reference to the BGL schema GraphDescriptor type. - */ -export type Board = GraphDescriptor; - -/** - * Union of {@link ResourceReference} and {@link Board} - */ -export type BoardReference = ResourceReference | Board; - -/** - * Union of {@link ResourceReference} and {@link BreadboardManifest} - */ -export type ManifestReference = ResourceReference | BreadboardManifest; - -/** - * - * - * @examples [ - * "My First Board", - * "Gist Manifest" - * ] - */ -export type Title = string; - -/** - * The tags for this board - */ -export type Tags = string[]; diff --git a/packages/manifest/src/isReference.ts b/packages/manifest/src/isReference.ts deleted file mode 100644 index bf9c5ea550e..00000000000 --- a/packages/manifest/src/isReference.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { ResourceReference } from "."; - -export const isReference = (value: unknown): value is ResourceReference => { - return ( - typeof value === "object" && - value !== null && - ("ref" in value || "reference" in value) - ); -}; diff --git a/packages/manifest/src/scripts/generate.ts b/packages/manifest/src/scripts/generate.ts deleted file mode 100755 index 8bd44b1a7f9..00000000000 --- a/packages/manifest/src/scripts/generate.ts +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env -S npx -y tsx --no-cache - -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import fs from "fs"; -import path, { dirname } from "path"; -import { type Config } from "ts-json-schema-generator"; -import { fileURLToPath } from "url"; -import { - ABSOLUTE_PACKAGE_ROOT -} from "./util/constants"; -import { generateSchemaFile } from "./util/generate-schema-file"; -import { generateSchemaId } from "./util/generate-schema-id"; - -function main() { - console.log("Beginning Breadboard Manifest schema generation..."); - const __filename = fileURLToPath(import.meta.url); - const __dirname = dirname(__filename); - - const filePath = path.join(ABSOLUTE_PACKAGE_ROOT, "src", "index.ts"); - - if (fs.existsSync(filePath)) { - console.log(`Using file: ${filePath}`); - } else { - throw new Error( - `File not found: ${JSON.stringify({ ABSOLUTE_PACKAGE_ROOT, origin: __filename, __dirname, filePath }, null, 2)}` - ); - } - - const tsconfigPath = path.join(ABSOLUTE_PACKAGE_ROOT, "tsconfig.json"); - if (fs.existsSync(tsconfigPath)) { - console.log(`Using tsconfig: ${tsconfigPath}`); - } else { - throw new Error(`File not found: ${tsconfigPath}`); - } - - const baseConfig: Partial = { - type: "BreadboardManifest", - path: filePath, - tsconfig: tsconfigPath, - }; - - // Running with skipTypeCheck: true is necessary to generate the initial unchecked schema file. Otherwise, the script will fail with a type error. - generateSchemaFile({ - ...baseConfig, - skipTypeCheck: true, - }); - - const result = generateSchemaFile({ - ...baseConfig, - skipTypeCheck: true, - }); - - console.log(JSON.stringify({ result }, null, 2)); -} - -export const DEFAULT_CONFIG: Partial = { - additionalProperties: false, - expose: "all", - schemaId: generateSchemaId("tag"), - sortProps: true, - topRef: true, - jsDoc: "extended", -}; - -export function isObject(v: unknown): v is Record { - return "[object Object]" === Object.prototype.toString.call(v); -} - -main(); diff --git a/packages/manifest/src/scripts/util/ascend-to-package-dir.ts b/packages/manifest/src/scripts/util/ascend-to-package-dir.ts deleted file mode 100644 index 90f65929907..00000000000 --- a/packages/manifest/src/scripts/util/ascend-to-package-dir.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import fs from "fs"; -import path from "path"; - -export function ascendToPackageDir(packageName: string) { - let directory = import.meta.dirname; - while (directory !== "/") { - const packageJsonPath = path.join(directory, "package.json"); - if (fs.existsSync(packageJsonPath)) { - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")); - if (packageJson.name === packageName) { - return directory; - } - } - directory = path.dirname(directory); - } - throw new Error("Could not find breadboard-ai directory."); -} diff --git a/packages/manifest/src/scripts/util/constants.ts b/packages/manifest/src/scripts/util/constants.ts deleted file mode 100644 index e9ee17ca074..00000000000 --- a/packages/manifest/src/scripts/util/constants.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import path from "path"; -import { ascendToPackageDir } from "./ascend-to-package-dir"; - -export const PACKAGE_NAME: string = "@breadboard-ai/manifest" as const; -export const ABSOLUTE_PACKAGE_ROOT: string = ascendToPackageDir(PACKAGE_NAME); -export const SCHEMA_FILE_NAME: string = "bbm.schema.json" as const; -export const ABSOLUTE_PACKAGE_JSON_PATH: string = path.join( - ABSOLUTE_PACKAGE_ROOT, - "package.json" -); -export const ABSOLUTE_SCHEMA_PATH: string = path.join( - ABSOLUTE_PACKAGE_ROOT, - SCHEMA_FILE_NAME -); -export const HEAD_SCHEMA_FILE_NAME: string = ["head", SCHEMA_FILE_NAME].join( - "." -); -export const ABSOLUTE_HEAD_SCHEMA_PATH: string = path.join( - ABSOLUTE_PACKAGE_ROOT, - HEAD_SCHEMA_FILE_NAME -); - -export const GITHUB_OWNER: string = "breadboard-ai" as const; -export const GITHUB_REPO: string = "breadboard" as const; -export const REPO_PACKAGE_PATH: string = "packages/manifest" as const; diff --git a/packages/manifest/src/scripts/util/generate-schema-file.ts b/packages/manifest/src/scripts/util/generate-schema-file.ts deleted file mode 100644 index afc7535b73a..00000000000 --- a/packages/manifest/src/scripts/util/generate-schema-file.ts +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { $id as boardSchemaId } from "@google-labs/breadboard-schema/breadboard.schema.json" with { type: "json" }; -import fs from "fs"; -import { Schema, createGenerator, type Config } from "ts-json-schema-generator"; -import { DEFAULT_CONFIG } from "../generate"; -import { ABSOLUTE_SCHEMA_PATH } from "./constants"; -import { sortObject } from "./sort-objects"; -export function generateSchemaFile( - conf: Partial = {}, - postProcessor: (s: Schema) => Schema = (s: Schema): Schema => { - - const graphDescriptorRef = `${boardSchemaId}#/definitions/GraphDescriptor`; - - s.definitions!["Board"] = { - ...(s.definitions!["Board"] as Schema), - type: "object", - $ref: graphDescriptorRef, - // additionalProperties: false, // left to be applied once schema package is updated - } satisfies Schema; - - return sortObject(s); - } -) { - console.debug( - "Generating schema with config:", - JSON.stringify(conf, null, 2) - ); - - const mergedConfig: Config = { - ...DEFAULT_CONFIG, - ...conf, - }; - - const schema: Schema = postProcessor( - createGenerator(mergedConfig).createSchema(mergedConfig.type) - ); - - const schemaString = JSON.stringify(schema, null, "\t"); - fs.writeFileSync(ABSOLUTE_SCHEMA_PATH, schemaString); - - return { - destination: ABSOLUTE_SCHEMA_PATH, - schema, - }; -} diff --git a/packages/manifest/src/scripts/util/generate-schema-id.ts b/packages/manifest/src/scripts/util/generate-schema-id.ts deleted file mode 100644 index 15162912e3d..00000000000 --- a/packages/manifest/src/scripts/util/generate-schema-id.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import fs from "fs"; -import path from "path"; -import { - ABSOLUTE_PACKAGE_JSON_PATH, - GITHUB_OWNER, - GITHUB_REPO, - PACKAGE_NAME, - REPO_PACKAGE_PATH, - SCHEMA_FILE_NAME -} from "./constants"; - -/** - * - * @param mode "head" | "tag" - "head" for the main branch, "tag" for the tag associated with the current package version - * @returns The schema ID for the Breadboard Manifest schema. - */ -export function generateSchemaId( - mode: "head" | "tag" = "head", - schemaPath: string = SCHEMA_FILE_NAME -): string { - const ref = mode === "head" ? "main" : getTagRef(); - - return `https://raw.githubusercontent.com/${GITHUB_OWNER}/${GITHUB_REPO}/${ref}/${REPO_PACKAGE_PATH}/${schemaPath}`; -} - -export function getTagRef(): string { - const packageVersion = loadPackageJson().version; - if (!packageVersion) { - throw new Error("Package version not found in package.json"); - } - return `${PACKAGE_NAME}@${packageVersion}`; -} - -function loadPackageJson() { - return JSON.parse(fs.readFileSync(ABSOLUTE_PACKAGE_JSON_PATH, "utf-8")); -} diff --git a/packages/manifest/src/scripts/util/sort-objects.ts b/packages/manifest/src/scripts/util/sort-objects.ts deleted file mode 100644 index f3b9f9dfda5..00000000000 --- a/packages/manifest/src/scripts/util/sort-objects.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { isObject } from "../generate"; - -export function sortObject(obj: unknown): object { - if (Array.isArray(obj)) { - return obj.sort().map((value) => sortObject(value)); - } else if (isObject(obj)) { - return Object.keys(obj) - .sort() - .reduce( - (acc, key) => { - acc[key] = sortObject(obj[key]); - return acc; - }, - {} as Record - ); - } else { - return obj as object; - } -} diff --git a/packages/manifest/src/tests/index.test.ts b/packages/manifest/src/tests/index.test.ts deleted file mode 100644 index c6f17a55673..00000000000 --- a/packages/manifest/src/tests/index.test.ts +++ /dev/null @@ -1,203 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { base } from "@google-labs/breadboard"; -import Ajv, { type ValidateFunction } from "ajv"; -import addFormats from "ajv-formats"; -import fs from "fs"; -import * as assert from "node:assert"; -import test, { describe } from "node:test"; -import { BreadboardManifest } from ".."; -import { ABSOLUTE_SCHEMA_PATH } from "../scripts/util/constants"; - -const ajv: Ajv = new Ajv({ - allErrors: true, - strict: true, - strictTypes: true, - validateFormats: true, - validateSchema: true, - verbose: true, - loadSchema: async (uri: string) => { - const response = await fetch(uri); - if (response.ok) { - const json = await response.json(); - if (ajv.validateSchema(json)) { - return json; - } - } - throw new Error(`Loading error: ${response.status}`); - }, -}); - -addFormats(ajv); - -const readSchemaFile = fs.readFileSync(ABSOLUTE_SCHEMA_PATH, "utf-8"); -const parsedSchema = JSON.parse(readSchemaFile); -const validate = await ajv.compileAsync(parsedSchema); - -const manifestArray: BreadboardManifest[] = [ - {}, - { title: "Empty manifest" }, - { title: "Manifest with an empty boards array", boards: [] }, - { title: "Manifest with an empty manifests array", manifests: [] }, - { - title: "Manifest with a hard-coded board", - boards: [ - { - edges: [ - { - from: "input-1", - to: "output-2", - out: "*", - in: "", - }, - ], - nodes: [ - { - id: "output-2", - type: "output", - configuration: {}, - }, - { - id: "input-1", - type: "input", - configuration: {}, - }, - ], - }, - ], - }, - { - title: "Manifest with a generated board", - boards: [await base.input().to(base.output()).serialize({})], - }, - { - title: "Manifest with empty boards and manifests arrays", - boards: [], - manifests: [], - }, - { - title: "Manifest with boards", - boards: [ - { - title: "My First Board", - reference: - "https://gist.githubusercontent.com/user/SOME_ID/raw/board.bgl.json", - }, - { - title: "My Second Board", - reference: "./boards/board.bgl.json", - }, - ], - }, - { - title: "Manifest with tags", - boards: [ - { - title: "My Second Board", - reference: "./boards/board.bgl.json", - tags: ["tool"], - }, - ], - }, - { - title: "Manifest with manifests", - manifests: [ - { - title: "Gist Manifest", - reference: - "https://gist.githubusercontent.com/user/SOME_ID/raw/manifest.bbm.json", - }, - ], - }, - { - title: "Manifest with boards and manifests", - boards: [ - { - title: "My First Board", - reference: - "https://gist.githubusercontent.com/user/SOME_ID/raw/board.bgl.json", - }, - { - title: "My Second Board", - reference: "./boards/board.bgl.json", - }, - ], - manifests: [ - { - title: "Gist Manifest", - reference: - "https://gist.githubusercontent.com/user/SOME_ID/raw/manifest.bbm.json", - }, - ], - }, - { - title: "Nested manifest", - manifests: [ - { - title: "Gist Manifest", - reference: - "https://gist.githubusercontent.com/user/SOME_ID/raw/manifest.bbm.json", - }, - { - title: "Nested Nested Manifest", - boards: [ - { - title: "My First Board", - reference: - "https://gist.githubusercontent.com/user/SOME_ID/raw/board.bgl.json", - }, - ], - manifests: [ - { - title: "Nested Nested Nested Manifest", - boards: [ - { - title: "My First Board", - reference: - "https://gist.githubusercontent.com/user/SOME_ID/raw/board.bgl.json", - }, - ], - }, - ], - }, - ], - }, -]; - -describe("Schema Tests", () => { - test("Schema is valid.", async () => { - assert.ok(validate); - }); - describe("Validation Tests", () => { - manifestArray.forEach((manifest, index) => { - test(`Manifest ${index + 1}/${manifestArray.length}: ${manifest.title || ""}`, async () => { - const valid = validate(manifest); - const errors = validate.errors; - if (errors) { - throw new Error(`errors: ${JSON.stringify(errors, null, 2)}`); - } - assert.ok(!errors); - assert.ok(valid); - }); - }); - }); -}); - -function writeManifestJson() { - fs.writeFileSync( - "./manifest.bbm.json", - JSON.stringify( - { - $schema: "./bbm.schema.json", - title: "Manifest with boards and manifests", - manifests: manifestArray, - }, - null, - 2 - ) - ); -} diff --git a/packages/manifest/tsconfig.json b/packages/manifest/tsconfig.json deleted file mode 100644 index b6564c6b2d1..00000000000 --- a/packages/manifest/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "compilerOptions": { - "allowSyntheticDefaultImports": true, - "composite": false, - "declaration": true, - "declarationMap": true, - "esModuleInterop": true, - "isolatedModules": true, - "module": "ESNext", - "moduleResolution": "Node", - "outDir": "dist", - "resolveJsonModule": true, - "rootDir": "src", - "target": "ESNext" - }, - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/node-nursery-web/.eslintrc b/packages/node-nursery-web/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/node-nursery-web/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/node-nursery-web/.npmignore b/packages/node-nursery-web/.npmignore deleted file mode 100644 index 7ddb2133685..00000000000 --- a/packages/node-nursery-web/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -tsconfig.tsbuildinfo diff --git a/packages/node-nursery-web/CHANGELOG.md b/packages/node-nursery-web/CHANGELOG.md deleted file mode 100644 index 3620ce5d4df..00000000000 --- a/packages/node-nursery-web/CHANGELOG.md +++ /dev/null @@ -1,367 +0,0 @@ -# @google-labs/node-nursery-web - -## 1.3.2 - -### Patch Changes - -- Updated dependencies [703f17d] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [4dadf16] -- Updated dependencies [8f9fddf] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [9797718] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [a039d2e] -- Updated dependencies [9783ba8] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [d7606d3] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] - - @google-labs/breadboard@0.27.0 - -## 1.3.1 - -### Patch Changes - -- Updated dependencies [7d46a63] - - @google-labs/breadboard@0.26.0 - -## 1.3.0 - -### Minor Changes - -- 7de241c: Remove `BoardRunner`. - -### Patch Changes - -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @google-labs/breadboard@0.25.0 - -## 1.2.0 - -### Minor Changes - -- 00cc2c5: Remove `lambda`, introduce standalone `invokeGraph` and `runGraph` functions, and other plumbing refactoring. - -### Patch Changes - -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [1dc645a] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [c04cff0] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - -## 1.1.6 - -### Patch Changes - -- Updated dependencies [1e1be2a] -- Updated dependencies [2b094a3] -- Updated dependencies [fa93c3f] -- Updated dependencies [215bd15] -- Updated dependencies [2b9ef5b] -- Updated dependencies [a0852df] -- Updated dependencies [2312443] -- Updated dependencies [6ffa89c] - - @google-labs/breadboard@0.23.0 - -## 1.1.5 - -### Patch Changes - -- Updated dependencies [a925cf0] -- Updated dependencies [5cf08f1] -- Updated dependencies [ffbf163] -- Updated dependencies [8928fb7] -- Updated dependencies [d6706f2] -- Updated dependencies [5447426] -- Updated dependencies [7e1f01c] - - @google-labs/breadboard@0.22.0 - -## 1.1.4 - -### Patch Changes - -- Updated dependencies [5a55b7d] -- Updated dependencies [74ade20] -- Updated dependencies [59dd0f5] -- Updated dependencies [417323c] -- Updated dependencies [b3aa884] -- Updated dependencies [3d7b4a7] -- Updated dependencies [7af14cf] -- Updated dependencies [fea8967] -- Updated dependencies [778f7aa] -- Updated dependencies [808f5e2] -- Updated dependencies [e0fdbc3] -- Updated dependencies [54b03b9] -- Updated dependencies [810d7fd] -- Updated dependencies [14853d5] -- Updated dependencies [8798514] -- Updated dependencies [eb64b9a] -- Updated dependencies [32a48a3] -- Updated dependencies [cd73b17] -- Updated dependencies [81d82fe] -- Updated dependencies [2a7531b] -- Updated dependencies [7c1b4cb] -- Updated dependencies [702cfe1] -- Updated dependencies [bebd96e] -- Updated dependencies [91cb723] -- Updated dependencies [3e10f0f] -- Updated dependencies [c53ca01] -- Updated dependencies [4c681cb] -- Updated dependencies [fb2e584] -- Updated dependencies [9491266] -- Updated dependencies [2ace620] -- Updated dependencies [fcef799] -- Updated dependencies [37418d9] -- Updated dependencies [083f69c] -- Updated dependencies [5b03d96] -- Updated dependencies [f0d8d67] -- Updated dependencies [836389d] -- Updated dependencies [225c7cc] - - @google-labs/breadboard@0.21.0 - -## 1.1.3 - -### Patch Changes - -- Updated dependencies [8097177] -- Updated dependencies [cec6d54] -- Updated dependencies [3397974] -- Updated dependencies [ab9a4ce] -- Updated dependencies [a35406c] -- Updated dependencies [477e6e6] - - @google-labs/breadboard@0.20.0 - -## 1.1.2 - -### Patch Changes - -- Updated dependencies [63eb779] - - @google-labs/breadboard@0.19.0 - -## 1.1.1 - -### Patch Changes - -- 416aed2: Introduce `metadata` for `NodeHandler` entries, teaching node types in Kits to describe themselves. -- Updated dependencies [cef20ca] -- Updated dependencies [fbf7a83] -- Updated dependencies [54baba8] -- Updated dependencies [49c3aa1] -- Updated dependencies [cdc23bb] -- Updated dependencies [416aed2] -- Updated dependencies [a1fcaea] -- Updated dependencies [c3ed6a7] -- Updated dependencies [3d48482] -- Updated dependencies [f2eda0b] -- Updated dependencies [626139b] -- Updated dependencies [bd44e29] -- Updated dependencies [43da00a] -- Updated dependencies [c3587e1] -- Updated dependencies [3f9507d] - - @google-labs/breadboard@0.18.0 - -## 1.1.0 - -### Minor Changes - -- cffceb9: Remove `credentials` and `driveList` nodes. - -### Patch Changes - -- Updated dependencies [c3cb25f] -- Updated dependencies [ae79e4a] -- Updated dependencies [72c5c6b] -- Updated dependencies [dd810dd] -- Updated dependencies [c5ba396] -- Updated dependencies [7bafa40] -- Updated dependencies [2932f4b] -- Updated dependencies [51159c4] -- Updated dependencies [6f9ba52] - - @google-labs/breadboard@0.17.0 - -## 1.0.8 - -### Patch Changes - -- Updated dependencies [ad9c233] -- Updated dependencies [65d869b] -- Updated dependencies [417cdf5] -- Updated dependencies [cf0ee4f] -- Updated dependencies [43cbed7] -- Updated dependencies [ff6433c] -- Updated dependencies [5382365] -- Updated dependencies [0e7f106] -- Updated dependencies [9ea6ba0] -- Updated dependencies [ffd2a6c] - - @google-labs/breadboard@0.16.0 - -## 1.0.7 - -### Patch Changes - -- Updated dependencies [76da09d] -- Updated dependencies [938015d] - - @google-labs/breadboard@0.15.0 - -## 1.0.6 - -### Patch Changes - -- Updated dependencies [e8d0737] - - @google-labs/breadboard@0.14.0 - -## 1.0.5 - -### Patch Changes - -- Updated dependencies [faf1e12] -- Updated dependencies [51a38c0] -- Updated dependencies [d49b80e] -- Updated dependencies [9326bd7] -- Updated dependencies [fbad949] - - @google-labs/breadboard@0.13.0 - -## 1.0.4 - -### Patch Changes - -- Updated dependencies [99446b8] -- Updated dependencies [866fc36] -- Updated dependencies [a8bab08] -- Updated dependencies [decfa29] -- Updated dependencies [f005b3b] -- Updated dependencies [dcfdc37] -- Updated dependencies [d971aad] -- Updated dependencies [048e8ec] -- Updated dependencies [dc35601] -- Updated dependencies [9cda2ff] -- Updated dependencies [60bd63c] -- Updated dependencies [764ccda] -- Updated dependencies [04d5420] -- Updated dependencies [56b90a4] -- Updated dependencies [1b48826] -- Updated dependencies [e648f64] -- Updated dependencies [ad5c1be] -- Updated dependencies [4a4a1f6] -- Updated dependencies [bac9bb1] -- Updated dependencies [3e8cfcf] -- Updated dependencies [986af39] -- Updated dependencies [3c497b0] -- Updated dependencies [eabd97b] -- Updated dependencies [2008f69] -- Updated dependencies [c0f785a] -- Updated dependencies [a8fc3f3] -- Updated dependencies [32cfbaf] -- Updated dependencies [8dc4e00] -- Updated dependencies [6438930] -- Updated dependencies [dd2cce6] -- Updated dependencies [cac4f4f] -- Updated dependencies [b1fc53b] -- Updated dependencies [ef05634] -- Updated dependencies [c208cfc] - - @google-labs/breadboard@0.12.0 - -## 1.0.3 - -### Patch Changes - -- 56ccae5: Introduce a way to inspect kits. -- Updated dependencies [c19513e] -- Updated dependencies [2237a4c] -- Updated dependencies [bd68ebd] -- Updated dependencies [9a76a87] -- Updated dependencies [ea652f3] -- Updated dependencies [56954c1] -- Updated dependencies [0085ee2] -- Updated dependencies [0ef9ec5] -- Updated dependencies [ee00249] -- Updated dependencies [c13513f] -- Updated dependencies [56ccae5] -- Updated dependencies [4920d90] -- Updated dependencies [10a8129] -- Updated dependencies [c804ccc] -- Updated dependencies [5a65297] -- Updated dependencies [53406ad] -- Updated dependencies [4c5b853] -- Updated dependencies [3f3f090] -- Updated dependencies [d7a7903] -- Updated dependencies [4401a98] -- Updated dependencies [f6e9b2c] - - @google-labs/breadboard@0.11.0 - -## 1.0.2 - -### Patch Changes - -- Updated dependencies [9bcd607] -- Updated dependencies [f6a7f43] - - @google-labs/breadboard@0.10.0 - -## 1.0.1 - -### Patch Changes - -- f32504b: Actual first publish of node-nursery-web - -## 1.0.0 - -### Major Changes - -- deb0d19: Initial publish of node-nursery-web - -## 0.0.3 - -### Patch Changes - -- Updated dependencies [8eccdad] -- Updated dependencies [6e8c08d] -- Updated dependencies [780909c] -- Updated dependencies [bba68fd] -- Updated dependencies [b557794] -- Updated dependencies [a9206fc] -- Updated dependencies [931a95b] - - @google-labs/breadboard@0.9.0 - -## 0.0.2 - -### Patch Changes - -- Updated dependencies [af00e58] - - @google-labs/breadboard@0.8.0 diff --git a/packages/node-nursery-web/README.md b/packages/node-nursery-web/README.md deleted file mode 100644 index 5826e9fb1b4..00000000000 --- a/packages/node-nursery-web/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Breadboard Node Nursery Web - -A place for experimenting with board nodes that aren't yet ready for their own package (web specific) diff --git a/packages/node-nursery-web/package.json b/packages/node-nursery-web/package.json deleted file mode 100644 index 439dfac0b56..00000000000 --- a/packages/node-nursery-web/package.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "name": "@google-labs/node-nursery-web", - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "version": "1.3.2", - "description": "A Nursery for new nodes that run in both Web and Node environments. Move to other kits to publish.", - "main": "./dist/src/index.js", - "exports": "./dist/src/index.js", - "types": "dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "test": "wireit", - "build": "wireit", - "build:tsc": "wireit", - "lint": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "../breadboard:build", - "../template-kit:build", - "build:tsc" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "../breadboard:build:tsc", - "../core-kit:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "test": { - "command": "ava", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - } - }, - "repository": { - "directory": "packages/node-nursery-web", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src" - ], - "ava": { - "timeout": "30s", - "files": [ - "tests/**/*.ts" - ], - "workerThreads": false, - "typescript": { - "rewritePaths": { - "./": "dist/" - }, - "compile": false - } - }, - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/template-kit": "^0.3.10", - "@google-labs/tsconfig": "^0.0.1", - "@types/gapi": "^0.0.47", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "npm": "^10.8.3", - "typescript": "^5.6.2" - }, - "dependencies": { - "@google-labs/breadboard": "^0.27.0" - } -} diff --git a/packages/node-nursery-web/src/index.ts b/packages/node-nursery-web/src/index.ts deleted file mode 100644 index 033f7759720..00000000000 --- a/packages/node-nursery-web/src/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { KitBuilder } from "@google-labs/breadboard/kits"; -import transformStream from "./nodes/transform-stream.js"; -import listToStream from "./nodes/list-to-stream.js"; - -const NodeNurseryWeb = new KitBuilder({ - title: "Node Nursery (Web)", - description: - "A kit that holds nodes that run in a Web-based environment, and are still WIP", - url: "npm:@google-labs/node-nursery-web", -}).build({ - transformStream, - listToStream, -}); - -export default NodeNurseryWeb; -export type NodeNurseryWeb = InstanceType; -export { NodeNurseryWeb }; - -/** - * This is a wrapper around existing kits for the new syntax to add types. - * - * This should transition to a codegen step, with typescript types constructed - * from .describe() calls. - */ -import { - addKit, - NewNodeValue as NodeValue, - NewNodeFactory as NodeFactory, -} from "@google-labs/breadboard"; - -export const nursery = addKit(NodeNurseryWeb) as unknown as { - transformStream: NodeFactory< - { stream: NodeValue; board: NodeValue; decode?: boolean }, - { stream: NodeValue } - >; - listToStream: NodeFactory<{ list: NodeValue[] }, { stream: NodeValue }>; - // TODO: Other NodeNurseryWeb nodes. -}; diff --git a/packages/node-nursery-web/src/nodes/list-to-stream.ts b/packages/node-nursery-web/src/nodes/list-to-stream.ts deleted file mode 100644 index 6151e1fe218..00000000000 --- a/packages/node-nursery-web/src/nodes/list-to-stream.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - InputValues, - NodeHandler, - OutputValues, - StreamCapability, -} from "@google-labs/breadboard"; - -export default { - metadata: { - deprecated: true, - }, - invoke: async (inputs: InputValues): Promise => { - const { list } = inputs; - if (!list) throw new Error("The `list` input is required"); - if (!Array.isArray(list)) - throw new Error("The `list` input must be an array"); - const stream = new ReadableStream({ - async start(controller) { - for (const item of list) { - controller.enqueue({ chunk: item }); - controller.enqueue({ chunk: " " }); - } - controller.close(); - }, - }); - return { stream: new StreamCapability(stream) }; - }, -} satisfies NodeHandler; diff --git a/packages/node-nursery-web/src/nodes/transform-stream.ts b/packages/node-nursery-web/src/nodes/transform-stream.ts deleted file mode 100644 index 58667caf243..00000000000 --- a/packages/node-nursery-web/src/nodes/transform-stream.ts +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - BreadboardCapability, - InputValues, - NodeHandlerContext, - NodeHandlerObject, - OutputValues, - StreamCapability, - StreamCapabilityType, - getGraphDescriptor, - invokeGraph, - isStreamCapability, -} from "@google-labs/breadboard"; - -export type TransformStreamInputs = InputValues & { - stream: StreamCapabilityType; - decode?: boolean; - board?: BreadboardCapability; -}; - -const getTransformer = async ( - board?: BreadboardCapability, - context?: NodeHandlerContext -): Promise => { - if (board) { - const runnableBoard = await getGraphDescriptor( - board as BreadboardCapability, - context - ); - if (!runnableBoard) throw new Error("Invalid board"); - // Because stream transformers run outside of the normal board lifecycle, - // they will not have access to `probe` capabilities and thus will not - // send diagnostics back. - // We need to figure out how enable this. - return { - async transform(chunk, controller) { - const inputs = { chunk }; - const result = await invokeGraph(runnableBoard, inputs, { - ...context, - // TODO: figure out how to send diagnostics from streams transformer. - probe: undefined, - }); - controller.enqueue({ chunk: result.chunk }); - }, - }; - } else - return { - transform(chunk, controller) { - controller.enqueue(chunk); - }, - }; -}; - -export default { - metadata: { - deprecated: true, - }, - invoke: async ( - inputs: InputValues, - context?: NodeHandlerContext - ): Promise => { - const { stream, board, decode = false } = inputs as TransformStreamInputs; - if (!stream) throw new Error("The `stream` input is required"); - if (!isStreamCapability(stream)) - throw new Error("The `stream` input must be a `StreamCapability`."); - const transformer = await getTransformer(board, context); - const streamCapability = stream as StreamCapabilityType; - const decoder = decode ? new TextDecoderStream() : new TransformStream(); - const outputStream = streamCapability.stream - .pipeThrough(decoder) - .pipeThrough(new TransformStream(transformer)); - return { stream: new StreamCapability(outputStream) }; - }, -} satisfies NodeHandlerObject; diff --git a/packages/node-nursery-web/tests/transform-stream.ts b/packages/node-nursery-web/tests/transform-stream.ts deleted file mode 100644 index aee7f79936a..00000000000 --- a/packages/node-nursery-web/tests/transform-stream.ts +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import transformStream, { - TransformStreamInputs, -} from "../src/nodes/transform-stream.js"; -import { - Board, - BreadboardCapability, - GraphDescriptor, - StreamCapability, - StreamCapabilityType, - callHandler, -} from "@google-labs/breadboard"; - -const toArray = async (stream: ReadableStream) => { - const results: T[] = []; - await stream.pipeTo( - new WritableStream({ - write(chunk) { - results.push(chunk); - }, - }) - ); - return results; -}; - -test("transform stream noop", async (t) => { - const stream = new ReadableStream({ - start(controller) { - controller.enqueue(1); - controller.enqueue(2); - controller.enqueue(3); - controller.close(); - }, - }); - const inputs: TransformStreamInputs = { - stream: new StreamCapability(stream), - }; - const outputs = (await callHandler(transformStream, inputs, {})) as { - stream: StreamCapabilityType; - }; - const results = await toArray(outputs.stream.stream); - t.deepEqual(results, [1, 2, 3]); -}); - -test("transform stream noop with text decoding", async (t) => { - const stream = new ReadableStream({ - start(controller) { - const encoder = new TextEncoder(); - controller.enqueue(encoder.encode("one")); - controller.enqueue(encoder.encode("two")); - controller.enqueue(encoder.encode("three")); - controller.close(); - }, - }); - const inputs: TransformStreamInputs = { - stream: new StreamCapability(stream), - decode: true, - }; - const outputs = (await callHandler(transformStream, inputs, {})) as { - stream: StreamCapabilityType; - }; - const results = await toArray(outputs.stream.stream); - t.deepEqual(results, ["one", "two", "three"]); -}); - -test("transform stream with a board", async (t) => { - const board = new Board(); - board.input().wire("chunk->", board.output()); - - const graph = board as GraphDescriptor; - - const stream = new ReadableStream({ - start(controller) { - controller.enqueue(1); - controller.enqueue(2); - controller.enqueue(3); - controller.close(); - }, - }); - const inputs: TransformStreamInputs = { - stream: new StreamCapability(stream), - board: { - kind: "board", - board: graph, - } as BreadboardCapability, - }; - const outputs = (await callHandler(transformStream, inputs, {})) as { - stream: StreamCapabilityType; - }; - const results = await toArray(outputs.stream.stream); - t.deepEqual(results, [{ chunk: 1 }, { chunk: 2 }, { chunk: 3 }]); -}); diff --git a/packages/node-nursery-web/tsconfig.json b/packages/node-nursery-web/tsconfig.json deleted file mode 100644 index 1ff943cd641..00000000000 --- a/packages/node-nursery-web/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "outDir": "./dist" - }, - "include": ["src/**/*", "tests/**/*"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/node-proxy-server/.eslintrc b/packages/node-proxy-server/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/node-proxy-server/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/node-proxy-server/.gitignore b/packages/node-proxy-server/.gitignore deleted file mode 100644 index 065bfcc66a6..00000000000 --- a/packages/node-proxy-server/.gitignore +++ /dev/null @@ -1,68 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -firebase-debug.log* -firebase-debug.*.log* - -# Firebase cache -.firebase/ - -# Firebase config - -# Uncomment this if you'd like others to create their own Firebase project. -# For a team working on the same Firebase project(s), it is recommended to leave -# it commented so all members can deploy to the same project(s) in .firebaserc. -# .firebaserc - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env - -lib \ No newline at end of file diff --git a/packages/node-proxy-server/.npmignore b/packages/node-proxy-server/.npmignore deleted file mode 100644 index 7ddb2133685..00000000000 --- a/packages/node-proxy-server/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -tsconfig.tsbuildinfo diff --git a/packages/node-proxy-server/CHANGELOG.md b/packages/node-proxy-server/CHANGELOG.md deleted file mode 100644 index cace9919525..00000000000 --- a/packages/node-proxy-server/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -# @google-labs/node-proxy-server - -## 0.0.2 - -### Patch Changes - -- 66128fa: Update node proxy server machinery diff --git a/packages/node-proxy-server/README.md b/packages/node-proxy-server/README.md deleted file mode 100644 index 70b908a3ae0..00000000000 --- a/packages/node-proxy-server/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Breadboard Node Proxy Server - -A library that allows running nodes remotely. - -This is a very simple implementation of a Breadboard node proxy server. The -purpose of a node proxy server is to run Breadboard nodes individually, usually -as part of a run elsewhere. - -In this example, some nodes are handled in the browser, and some are handled using this proxy server. - -### To deploy - -```bash -npm run deploy -``` - -### To serve locally - -```bash -npm run serve -``` diff --git a/packages/node-proxy-server/firebase.json b/packages/node-proxy-server/firebase.json deleted file mode 100644 index b3ced8807f4..00000000000 --- a/packages/node-proxy-server/firebase.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "functions": [ - { - "source": "functions", - "codebase": "default", - "ignore": [ - "node_modules", - ".git", - "firebase-debug.log", - "firebase-debug.*.log" - ], - "predeploy": [ - "npm --prefix \"$RESOURCE_DIR\" run build" - ] - } - ] -} diff --git a/packages/node-proxy-server/functions/.gitignore b/packages/node-proxy-server/functions/.gitignore deleted file mode 100644 index 65b4c06ecf8..00000000000 --- a/packages/node-proxy-server/functions/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Compiled JavaScript files -lib/**/*.js -lib/**/*.js.map - -# TypeScript v1 declaration files -typings/ - -# Node.js dependency directory -node_modules/ diff --git a/packages/node-proxy-server/functions/package.json b/packages/node-proxy-server/functions/package.json deleted file mode 100644 index 1e30236edc0..00000000000 --- a/packages/node-proxy-server/functions/package.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "name": "functions", - "type": "module", - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "build:tsc": "wireit", - "build:rollup": "wireit", - "serve": "wireit", - "shell": "npm run build && npx firebase functions:shell", - "start": "npm run shell", - "logs": "firebase functions:log" - }, - "wireit": { - "build": { - "dependencies": [ - "../../breadboard:build", - "../../template-kit:build", - "../../palm-kit:build", - "build:rollup", - "build:tsc" - ] - }, - "typescript-files-and-deps": { - "dependencies": [ - "../../breadboard:build:tsc", - "../../template-kit:build:tsc", - "../../palm-kit:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tsconfig.json" - ] - }, - "build:tsc": { - "command": "tsc --pretty", - "dependencies": [ - "typescript-files-and-deps" - ], - "files": [], - "output": [ - "lib/", - "!lib/bundle.js" - ], - "clean": "if-file-deleted" - }, - "build:rollup": { - "command": "rollup -c", - "dependencies": [ - "build:tsc" - ], - "files": [ - "rollup.config.js", - "package.json" - ], - "output": [ - "lib/bundle.js" - ] - }, - "serve": { - "command": "firebase emulators:start --only functions", - "service": true, - "dependencies": [ - { - "script": "typescript-files-and-deps", - "cascade": false - } - ], - "files": [ - ".env" - ] - } - }, - "main": "lib/bundle.js", - "dependencies": { - "firebase-admin": "^12.5.0", - "firebase-functions": "^6.0.1" - }, - "devDependencies": { - "@google-labs/breadboard": "^0.27.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/palm-kit": "^0.1.4", - "@google-labs/template-kit": "^0.3.10", - "@rollup/plugin-commonjs": "^28.0.0", - "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^15.3.0", - "@rollup/plugin-terser": "^0.4.4", - "firebase-functions-test": "^3.3.0", - "rollup": "^4.22.4", - "typescript": "^5.6.2" - }, - "private": true, - "version": "" -} diff --git a/packages/node-proxy-server/functions/public/index.html b/packages/node-proxy-server/functions/public/index.html deleted file mode 100644 index 0114e82d96c..00000000000 --- a/packages/node-proxy-server/functions/public/index.html +++ /dev/null @@ -1,121 +0,0 @@ - -Breadboard Node Proxy Server - -

    Breadboard Node Proxy Server

    - -

    API Tester

    - -
    - - - -
    -

    Results

    - -
    
    -
    - -
    - What is this? - -

    This is a node proxy server for Breadboard nodes.

    -

    The API is:

    -

    - POST / with a JSON body of the form: - -

    -[ "proxy", { node { type: { node type id } }, inputs: { ... } } ]
    - - The result will be a JSON object of the form: - -
    [ "proxy", outputs: { ... } ]
    -
    - Or, if an error has occurred: - -
    [ "proxy", error: { message: { the error message } } ]
    -
    -

    -
    - - diff --git a/packages/node-proxy-server/functions/rollup.config.js b/packages/node-proxy-server/functions/rollup.config.js deleted file mode 100644 index 419bffdce33..00000000000 --- a/packages/node-proxy-server/functions/rollup.config.js +++ /dev/null @@ -1,22 +0,0 @@ -import { nodeResolve } from "@rollup/plugin-node-resolve"; -import terser from "@rollup/plugin-terser"; -import commonjs from "@rollup/plugin-commonjs"; -import json from "@rollup/plugin-json"; - -export default { - external: ["firebase-functions/v2/https", "firebase-functions"], - input: "lib/index.js", - output: { - file: "lib/bundle.js", - sourcemap: "inline", - format: "esm", - plugins: [terser()], - }, - plugins: [ - nodeResolve({ - preferBuiltins: true, - }), - commonjs(), - json(), - ], -}; diff --git a/packages/node-proxy-server/functions/src/config.ts b/packages/node-proxy-server/functions/src/config.ts deleted file mode 100644 index 4ba5ef2121c..00000000000 --- a/packages/node-proxy-server/functions/src/config.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { asRuntimeKit } from "@google-labs/breadboard"; -import { defineConfig, hasOrigin } from "@google-labs/breadboard/remote"; -import TemplateKit from "@google-labs/template-kit"; -import PaLMKit from "@google-labs/palm-kit"; -import Core from "@google-labs/core-kit"; - -export default defineConfig({ - kits: [asRuntimeKit(TemplateKit), asRuntimeKit(PaLMKit), asRuntimeKit(Core)], - proxy: [ - "fetch", - "palm-generateText", - "palm-embedText", - "promptTemplate", - { - node: "secrets", - tunnel: { - PALM_KEY: ["palm-generateText", "palm-embedText"], - GEMINI_KEY: { - to: "fetch", - when: { - url: hasOrigin("https://generativelanguage.googleapis.com"), - }, - }, - GOOGLE_CSE_ID: { - to: "fetch", - when: { - url: hasOrigin("https://www.googleapis.com"), - }, - }, - API_KEY: { - to: "fetch", - when: { - url: hasOrigin("https://www.googleapis.com"), - }, - }, - OPENAI_API_KEY: { - to: "fetch", - when: { - url: hasOrigin("https://api.openai.com"), - }, - }, - }, - }, - ], -}); diff --git a/packages/node-proxy-server/functions/src/index.ts b/packages/node-proxy-server/functions/src/index.ts deleted file mode 100644 index 9cb2279a346..00000000000 --- a/packages/node-proxy-server/functions/src/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { onRequest } from "firebase-functions/v2/https"; -import { Request, Response, logger } from "firebase-functions"; - -import { - HTTPServerTransport, - ProxyServer, -} from "@google-labs/breadboard/remote"; - -import config from "./config.js"; - -const handleNonPostRequest = (request: Request, response: Response) => { - if (request.method === "POST") return false; - if (request.method !== "GET") { - response.status(405); - response.send("Method not allowed"); - return true; - } - if (request.path === "/") { - response.sendFile( - new URL("../public/index.html", import.meta.url).pathname - ); - return true; - } else { - response.status(404); - response.send("Not found"); - return true; - } -}; - -export const nodeProxyServer = onRequest( - { cors: true }, - async (request, response) => { - if (handleNonPostRequest(request, response)) return; - - const server = new ProxyServer(new HTTPServerTransport(request, response)); - try { - await server.serve(config); - } catch (e) { - logger.error(e); - response.status(500).send(`500 Server Error: ${(e as Error).message}`); - } - } -); diff --git a/packages/node-proxy-server/functions/tsconfig.json b/packages/node-proxy-server/functions/tsconfig.json deleted file mode 100644 index 6b378441590..00000000000 --- a/packages/node-proxy-server/functions/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "composite": false, - "declaration": true, - "declarationMap": true, - "incremental": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "inlineSources": false, - "lib": ["ES2022", "DOM"], - "module": "NodeNext", - "target": "ES2022", - "isolatedModules": true, - "allowJs": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "preserveWatchOutput": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "outDir": "./lib" - }, - "compileOnSave": true, - "include": ["src"] -} diff --git a/packages/node-proxy-server/package.json b/packages/node-proxy-server/package.json deleted file mode 100644 index aec9fa9f3d3..00000000000 --- a/packages/node-proxy-server/package.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "name": "@google-labs/node-proxy-server", - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "private": true, - "version": "0.0.2", - "description": "A sample implementation of a Breadboard Node proxy server", - "main": "./dist/src/index.js", - "exports": "./dist/src/index.js", - "types": "dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "serve": "wireit", - "build": "wireit", - "dev": "npm run serve --watch", - "lint": "wireit", - "deploy": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "./functions:build" - ] - }, - "serve": { - "command": "(cd functions && npm run serve)", - "dependencies": [ - "build" - ] - }, - "deploy": { - "command": "firebase deploy --only functions", - "dependencies": [ - "./functions:build" - ] - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build" - ], - "files": [ - "src/**/*.ts", - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - } - }, - "repository": { - "directory": "packages/node-proxy-server", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src" - ], - "ava": { - "timeout": "30s", - "files": [ - "tests/**/*.ts" - ], - "workerThreads": false, - "typescript": { - "rewritePaths": { - "./": "dist/" - }, - "compile": false - } - }, - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@google-labs/tsconfig": "^0.0.1", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "typescript": "^5.6.2" - } -} diff --git a/packages/node-proxy-server/src/index.ts b/packages/node-proxy-server/src/index.ts deleted file mode 100644 index 09aaa71d6fb..00000000000 --- a/packages/node-proxy-server/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -console.log("code goes here"); diff --git a/packages/node-proxy-server/tsconfig.json b/packages/node-proxy-server/tsconfig.json deleted file mode 100644 index 1ff943cd641..00000000000 --- a/packages/node-proxy-server/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "outDir": "./dist" - }, - "include": ["src/**/*", "tests/**/*"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/palm-kit/.eslintrc b/packages/palm-kit/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/palm-kit/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/palm-kit/.npmignore b/packages/palm-kit/.npmignore deleted file mode 100644 index 7ddb2133685..00000000000 --- a/packages/palm-kit/.npmignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -tsconfig.tsbuildinfo diff --git a/packages/palm-kit/CHANGELOG.md b/packages/palm-kit/CHANGELOG.md deleted file mode 100644 index 076ab10a374..00000000000 --- a/packages/palm-kit/CHANGELOG.md +++ /dev/null @@ -1,350 +0,0 @@ -# Changelog - -## 0.1.4 - -### Patch Changes - -- Updated dependencies [703f17d] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [4dadf16] -- Updated dependencies [8f9fddf] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [9797718] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [a039d2e] -- Updated dependencies [9783ba8] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [d7606d3] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] - - @google-labs/breadboard@0.27.0 - -## 0.1.3 - -### Patch Changes - -- Updated dependencies [7d46a63] - - @google-labs/breadboard@0.26.0 - -## 0.1.2 - -### Patch Changes - -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @google-labs/breadboard@0.25.0 - -## 0.1.1 - -### Patch Changes - -- Updated dependencies [8c694ed] -- Updated dependencies [bbf2c30] -- Updated dependencies [14df6a8] -- Updated dependencies [1dc645a] -- Updated dependencies [2aabb7a] -- Updated dependencies [fb72771] -- Updated dependencies [9b22cab] -- Updated dependencies [00cc2c5] -- Updated dependencies [c04cff0] -- Updated dependencies [3f8cdd1] -- Updated dependencies [3a5ced1] -- Updated dependencies [62f8d5b] - - @google-labs/breadboard@0.24.0 - -## 0.1.0 - -### Minor Changes - -- 2312443: Add support for `deprecated` and `experimental` tags on Kits. - -### Patch Changes - -- Updated dependencies [1e1be2a] -- Updated dependencies [2b094a3] -- Updated dependencies [fa93c3f] -- Updated dependencies [215bd15] -- Updated dependencies [2b9ef5b] -- Updated dependencies [a0852df] -- Updated dependencies [2312443] -- Updated dependencies [6ffa89c] - - @google-labs/breadboard@0.23.0 - -## 0.0.16 - -### Patch Changes - -- Updated dependencies [a925cf0] -- Updated dependencies [5cf08f1] -- Updated dependencies [ffbf163] -- Updated dependencies [8928fb7] -- Updated dependencies [d6706f2] -- Updated dependencies [5447426] -- Updated dependencies [7e1f01c] - - @google-labs/breadboard@0.22.0 - -## 0.0.15 - -### Patch Changes - -- Updated dependencies [5a55b7d] -- Updated dependencies [74ade20] -- Updated dependencies [59dd0f5] -- Updated dependencies [417323c] -- Updated dependencies [b3aa884] -- Updated dependencies [3d7b4a7] -- Updated dependencies [7af14cf] -- Updated dependencies [fea8967] -- Updated dependencies [778f7aa] -- Updated dependencies [808f5e2] -- Updated dependencies [e0fdbc3] -- Updated dependencies [54b03b9] -- Updated dependencies [810d7fd] -- Updated dependencies [14853d5] -- Updated dependencies [8798514] -- Updated dependencies [eb64b9a] -- Updated dependencies [32a48a3] -- Updated dependencies [cd73b17] -- Updated dependencies [81d82fe] -- Updated dependencies [2a7531b] -- Updated dependencies [7c1b4cb] -- Updated dependencies [702cfe1] -- Updated dependencies [bebd96e] -- Updated dependencies [91cb723] -- Updated dependencies [3e10f0f] -- Updated dependencies [c53ca01] -- Updated dependencies [4c681cb] -- Updated dependencies [fb2e584] -- Updated dependencies [9491266] -- Updated dependencies [2ace620] -- Updated dependencies [fcef799] -- Updated dependencies [37418d9] -- Updated dependencies [083f69c] -- Updated dependencies [5b03d96] -- Updated dependencies [f0d8d67] -- Updated dependencies [836389d] -- Updated dependencies [225c7cc] - - @google-labs/breadboard@0.21.0 - -## 0.0.14 - -### Patch Changes - -- Updated dependencies [8097177] -- Updated dependencies [cec6d54] -- Updated dependencies [3397974] -- Updated dependencies [ab9a4ce] -- Updated dependencies [a35406c] -- Updated dependencies [477e6e6] - - @google-labs/breadboard@0.20.0 - -## 0.0.13 - -### Patch Changes - -- Updated dependencies [63eb779] - - @google-labs/breadboard@0.19.0 - -## 0.0.12 - -### Patch Changes - -- 416aed2: Introduce `metadata` for `NodeHandler` entries, teaching node types in Kits to describe themselves. -- Updated dependencies [cef20ca] -- Updated dependencies [fbf7a83] -- Updated dependencies [54baba8] -- Updated dependencies [49c3aa1] -- Updated dependencies [cdc23bb] -- Updated dependencies [416aed2] -- Updated dependencies [a1fcaea] -- Updated dependencies [c3ed6a7] -- Updated dependencies [3d48482] -- Updated dependencies [f2eda0b] -- Updated dependencies [626139b] -- Updated dependencies [bd44e29] -- Updated dependencies [43da00a] -- Updated dependencies [c3587e1] -- Updated dependencies [3f9507d] - - @google-labs/breadboard@0.18.0 - -## 0.0.11 - -### Patch Changes - -- Updated dependencies [c3cb25f] -- Updated dependencies [ae79e4a] -- Updated dependencies [72c5c6b] -- Updated dependencies [dd810dd] -- Updated dependencies [c5ba396] -- Updated dependencies [7bafa40] -- Updated dependencies [2932f4b] -- Updated dependencies [51159c4] -- Updated dependencies [6f9ba52] - - @google-labs/breadboard@0.17.0 - -## 0.0.10 - -### Patch Changes - -- Updated dependencies [ad9c233] -- Updated dependencies [65d869b] -- Updated dependencies [417cdf5] -- Updated dependencies [cf0ee4f] -- Updated dependencies [43cbed7] -- Updated dependencies [ff6433c] -- Updated dependencies [5382365] -- Updated dependencies [0e7f106] -- Updated dependencies [9ea6ba0] -- Updated dependencies [ffd2a6c] - - @google-labs/breadboard@0.16.0 - -## 0.0.9 - -### Patch Changes - -- Updated dependencies [76da09d] -- Updated dependencies [938015d] - - @google-labs/breadboard@0.15.0 - -## 0.0.8 - -### Patch Changes - -- Updated dependencies [e8d0737] - - @google-labs/breadboard@0.14.0 - -## 0.0.7 - -### Patch Changes - -- Updated dependencies [faf1e12] -- Updated dependencies [51a38c0] -- Updated dependencies [d49b80e] -- Updated dependencies [9326bd7] -- Updated dependencies [fbad949] - - @google-labs/breadboard@0.13.0 - -## 0.0.6 - -### Patch Changes - -- Updated dependencies [99446b8] -- Updated dependencies [866fc36] -- Updated dependencies [a8bab08] -- Updated dependencies [decfa29] -- Updated dependencies [f005b3b] -- Updated dependencies [dcfdc37] -- Updated dependencies [d971aad] -- Updated dependencies [048e8ec] -- Updated dependencies [dc35601] -- Updated dependencies [9cda2ff] -- Updated dependencies [60bd63c] -- Updated dependencies [764ccda] -- Updated dependencies [04d5420] -- Updated dependencies [56b90a4] -- Updated dependencies [1b48826] -- Updated dependencies [e648f64] -- Updated dependencies [ad5c1be] -- Updated dependencies [4a4a1f6] -- Updated dependencies [bac9bb1] -- Updated dependencies [3e8cfcf] -- Updated dependencies [986af39] -- Updated dependencies [3c497b0] -- Updated dependencies [eabd97b] -- Updated dependencies [2008f69] -- Updated dependencies [c0f785a] -- Updated dependencies [a8fc3f3] -- Updated dependencies [32cfbaf] -- Updated dependencies [8dc4e00] -- Updated dependencies [6438930] -- Updated dependencies [dd2cce6] -- Updated dependencies [cac4f4f] -- Updated dependencies [b1fc53b] -- Updated dependencies [ef05634] -- Updated dependencies [c208cfc] - - @google-labs/breadboard@0.12.0 - -## 0.0.5 - -### Patch Changes - -- Updated dependencies [c19513e] -- Updated dependencies [2237a4c] -- Updated dependencies [bd68ebd] -- Updated dependencies [9a76a87] -- Updated dependencies [ea652f3] -- Updated dependencies [56954c1] -- Updated dependencies [0085ee2] -- Updated dependencies [0ef9ec5] -- Updated dependencies [ee00249] -- Updated dependencies [c13513f] -- Updated dependencies [56ccae5] -- Updated dependencies [4920d90] -- Updated dependencies [10a8129] -- Updated dependencies [c804ccc] -- Updated dependencies [5a65297] -- Updated dependencies [53406ad] -- Updated dependencies [4c5b853] -- Updated dependencies [3f3f090] -- Updated dependencies [d7a7903] -- Updated dependencies [4401a98] -- Updated dependencies [f6e9b2c] - - @google-labs/breadboard@0.11.0 - -## 0.0.4 - -### Patch Changes - -- Updated dependencies [9bcd607] -- Updated dependencies [f6a7f43] - - @google-labs/breadboard@0.10.0 - -## 0.0.3 - -### Patch Changes - -- Updated dependencies [8eccdad] -- Updated dependencies [6e8c08d] -- Updated dependencies [780909c] -- Updated dependencies [bba68fd] -- Updated dependencies [b557794] -- Updated dependencies [a9206fc] -- Updated dependencies [931a95b] - - @google-labs/breadboard@0.9.0 - -## 0.0.2 - -### Patch Changes - -- Updated dependencies [af00e58] - - @google-labs/breadboard@0.8.0 - -## [0.0.1] - 2023-12-06 - -- The `generateText` and `embedText` node graduate to this kit. diff --git a/packages/palm-kit/README.md b/packages/palm-kit/README.md deleted file mode 100644 index 5b99f94528e..00000000000 --- a/packages/palm-kit/README.md +++ /dev/null @@ -1,78 +0,0 @@ -# Breadboard PaLM Kit - -> [!NOTICE] -> The PaLM API is now deprecated. See https://ai.google.dev/palm_docs for more. - -![Stability](https://img.shields.io/badge/stability-wip-green) [![Discord](https://img.shields.io/discord/1138546999872999556?logo=discord)](https://discord.gg/breadboard) - -A Breadboard Kit with nodes to access PaLM APIs. - -## Node Reference - -This kit contains the following nodes: - -### The `generateText` node - -This is a [PaLM API](https://developers.generativeai.google/) text completion node. To produce useful output, the node needs a `PALM_KEY` input and the `text` input. - -#### Example: - -Given this input: - -```json -{ - "PALM_KEY": "", - "text": "How old is planet Earth?" -} -``` - -The node will produce this output: - -```json -{ - "completion": "It is about 4.5 billion years old." -} -``` - -#### Inputs: - -- `PALM_KEY` required, must contain the Google Cloud Platform API key for the project has the "Generative Language API" API enabled. -- `text` required, sent as the prompt for the completion. -- `stopSequences` optional array of strings. These will be passed as the stop sequences to the completion API. - -#### Outputs: - -- `completion` - result of the PaLM API text completion. - -### The `embedText` node - -This is a [PaLM API](https://developers.generativeai.google/) text embedding node. Just like the `generateText` node, it needs a `PALM_KEY` input and the `text` input. - -#### Example: - -Given this input: - -```json -{ - "PALM_KEY": "", - "text": "How old is planet Earth?" -} -``` - -The node will output a 768-dimensional embedding of the text: - -```json -{ - "embedding": [0.1, ... ] -} -``` - -#### Inputs: - -- `PALM_KEY` required, must contain the Google Cloud Platform API key for the project has the "Generative Language API" API enabled. - -- `text` required, text to embed. - -#### Outputs: - -- `embedding` - result of the PaLM API text embedding, a 768-dimensional array of floating-point numbers. diff --git a/packages/palm-kit/package.json b/packages/palm-kit/package.json deleted file mode 100644 index 9361f136eb6..00000000000 --- a/packages/palm-kit/package.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "name": "@google-labs/palm-kit", - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "version": "0.1.4", - "description": "A Breadboard Kit with nodes to access PaLM APIs.", - "main": "./dist/src/index.js", - "exports": "./dist/src/index.js", - "types": "dist/src/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "test": "wireit", - "lint": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "../breadboard:build", - "build:tsc" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "../breadboard:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tests/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "test": { - "command": "ava", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "lint": { - "command": "eslint . --ext .ts", - "env": { - "FORCE_COLOR": "1" - }, - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - } - }, - "repository": { - "directory": "packages/palm-kit", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/src" - ], - "ava": { - "timeout": "30s", - "files": [ - "tests/**/*.ts" - ], - "workerThreads": false, - "typescript": { - "rewritePaths": { - "./": "dist/" - }, - "compile": false - } - }, - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "@types/node": "^22.0.0", - "ava": "^5.2.0", - "typescript": "^5.6.2", - "@google-labs/tsconfig": "^0.0.1" - }, - "dependencies": { - "@google-labs/breadboard": "^0.27.0", - "@google-labs/palm-lite": "^0.0.3" - } -} diff --git a/packages/palm-kit/src/index.ts b/packages/palm-kit/src/index.ts deleted file mode 100644 index 19bcf76822f..00000000000 --- a/packages/palm-kit/src/index.ts +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { KitBuilder } from "@google-labs/breadboard/kits"; - -import generateText from "./nodes/generate-text.js"; -import embedText from "./nodes/embed-text.js"; - -const builder = new KitBuilder({ - title: "PaLM Kit", - description: "A Breadboard Kit with nodes to access PaLM APIs.", - url: "npm:@google-labs/palm-kit", - tags: ["deprecated"], - namespacePrefix: "palm-", -}); - -export const PaLMKit = builder.build({ - /** - * Places an `generateText` node on the board. - * - * Use this node to generate text from a prompt. - * - * See [`generateText` node - * reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/palm-kit/README.md) for more information. - */ - generateText, - /** - * Places an `embedText` node on the board. - * - * Use this node to embed text. - * - * See [`embedText` node - * reference](https://github.com/breadboard-ai/breadboard/blob/main/packages/palm-kit/README.md) for more information. - */ - embedText, -}); - -export type PaLMKit = InstanceType; - -export default PaLMKit; - -/** - * This is a wrapper around existing kits for the new syntax to add types. - * - * This should transition to a codegen step, with typescript types constructed - * from .describe() calls. - */ -import { addKit, NewNodeFactory as NodeFactory } from "@google-labs/breadboard"; - -export const palm = addKit(PaLMKit, "palm-") as unknown as { - generateText: NodeFactory< - { text: string; PALM_KEY: string }, - { completion: string } - >; -}; diff --git a/packages/palm-kit/src/nodes/embed-text.ts b/packages/palm-kit/src/nodes/embed-text.ts deleted file mode 100644 index f51219c7c0c..00000000000 --- a/packages/palm-kit/src/nodes/embed-text.ts +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - NodeDescriberFunction, - type InputValues, - type NodeValue, - type OutputValues, - NodeHandler, -} from "@google-labs/breadboard"; -import { EmbedTextResponse, palm } from "@google-labs/palm-lite"; - -export type EmbedTextInputs = NodeValue & { - /** - * Text to embed. - */ - text: string; - /** - * The Google Cloud Platform API key - */ - PALM_KEY: string; -}; - -export const embedTextDescriber: NodeDescriberFunction = async () => { - return { - inputSchema: { - type: "object", - properties: { - text: { - title: "text", - description: "Prompt for text completion.", - type: "string", - }, - PALM_KEY: { - title: "PALM_KEY", - description: "The Google Cloud Platform API key", - type: "string", - }, - }, - required: ["text", "PALM_KEY"], - }, - outputSchema: { - type: "object", - properties: { - embedding: { - title: "embedding", - description: "The embedding of the text.", - type: "array", - items: { - type: "number", - }, - minItems: 768, - maxItems: 768, - }, - }, - required: ["embedding"], - }, - }; -}; - -export default { - metadata: { - title: "Embed Text", - description: - "Uses `embedding-gecko-001` model to generate an embedding of a given text", - }, - describe: embedTextDescriber, - invoke: async (inputs: InputValues): Promise => { - const values = inputs as EmbedTextInputs; - if (!values.PALM_KEY) - throw new Error("Embedding requires `PALM_KEY` input"); - if (!values.text) throw new Error("Embedding requires `text` input"); - - const query = { text: values.text }; - - let embedding: number[] | undefined; - // Because Embedding API is a bit flaky, we try a few times before giving up. - let tries = 3; - while (!embedding && tries-- > 0) { - try { - const request = palm(values.PALM_KEY).embedding(query); - const data = await fetch(request); - const response = (await data.json()) as EmbedTextResponse; - embedding = response?.embedding?.value; - } catch (e) { - // TODO: Implement proper error handling. - } - } - if (!embedding) - throw new Error(`No embedding returned for "${values.text}"`); - - return { embedding } as OutputValues; - }, -} satisfies NodeHandler; diff --git a/packages/palm-kit/src/nodes/generate-text.ts b/packages/palm-kit/src/nodes/generate-text.ts deleted file mode 100644 index 141a5f76f87..00000000000 --- a/packages/palm-kit/src/nodes/generate-text.ts +++ /dev/null @@ -1,151 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { - InputValues, - NodeValue, - OutputValues, - ErrorCapability, - NodeDescriberFunction, - NodeHandler, -} from "@google-labs/breadboard"; -import { - GenerateTextResponse, - SafetySetting, - Text, - palm, -} from "@google-labs/palm-lite"; - -export type GenerateTextOutputs = GenerateTextResponse & { - completion: string; -}; - -export type GenerateTextInputs = NodeValue & { - /** - * Prompt for text completion. - */ - text: string; - /** - * The Google Cloud Platform API key - */ - PALM_KEY: string; - /** - * Stop sequences - */ - stopSequences: string[]; - /** - * Safety settings - */ - safetySettings: SafetySetting[]; -}; - -export type GenerateTextError = ErrorCapability & { - inputs: GenerateTextInputs; - filters: GenerateTextResponse["filters"]; - safetyFeedback: GenerateTextResponse["safetyFeedback"]; -}; - -export const prepareRequest = (inputs: InputValues) => { - const values = inputs as GenerateTextInputs; - if (!values.PALM_KEY) - throw new Error("Text completion requires `PALM_KEY` input"); - if (!values.text) throw new Error("Text completion requires `text` input"); - - const prompt = new Text().text(values.text); - const stopSequences = values.stopSequences || []; - stopSequences.forEach((stopSequence) => prompt.addStopSequence(stopSequence)); - const safetySettings = values.safetySettings || []; - safetySettings.forEach((safetySetting) => - prompt.addSafetySetting(safetySetting.category, safetySetting.threshold) - ); - return palm(values.PALM_KEY).text(prompt); -}; - -export const prepareResponse = async ( - data: Response -): Promise => { - const json = await data.json(); - const response = json as GenerateTextResponse; - - const completion = response?.candidates?.[0]?.output as string; - if (completion) return { completion, ...json }; - else - return { - $error: { - kind: "error", - error: new Error( - "Palm generateText failed: " + - (data.ok ? JSON.stringify(json) : data.statusText) - ), - status: data.status, - ...json, - } as GenerateTextError, - } as OutputValues; -}; - -export const generateTextDescriber: NodeDescriberFunction = async () => { - return { - inputSchema: { - type: "object", - properties: { - text: { - title: "text", - description: "Prompt for text completion.", - type: "string", - }, - PALM_KEY: { - title: "PALM_KEY", - description: "The Google Cloud Platform API key", - type: "string", - }, - stopSequences: { - title: "stopSequences", - description: "Stop sequences", - type: "array", - items: { - type: "string", - }, - }, - safetySettings: { - title: "safetySettings", - description: "Safety settings", - type: "array", - items: { - type: "object", - required: ["category", "threshold"], - }, - }, - }, - required: ["text", "PALM_KEY"], - }, - outputSchema: { - type: "object", - properties: { - completion: { - title: "completion", - description: - "The generated text completion of the supplied text input.", - type: "string", - }, - $error: { - title: "$error", - description: "Error information, if any.", - type: "object", - }, - }, - }, - }; -}; - -export default { - metadata: { - deprecated: true, - }, - describe: generateTextDescriber, - invoke: async (inputs: InputValues) => { - return await prepareResponse(await fetch(prepareRequest(inputs))); - }, -} satisfies NodeHandler; diff --git a/packages/palm-kit/tests/generate-text.ts b/packages/palm-kit/tests/generate-text.ts deleted file mode 100644 index 3f8cdbbed73..00000000000 --- a/packages/palm-kit/tests/generate-text.ts +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import test from "ava"; - -import { prepareRequest, prepareResponse } from "../src/nodes/generate-text.js"; - -test("prepareRequest throws when there's no PALM_KEY", (t) => { - t.throws(() => prepareRequest({ text: "foo" })); -}); - -test("prepareRequest throws when there's no text", (t) => { - t.throws(() => prepareRequest({ PALM_KEY: "foo" })); -}); - -test("prepareRequest returns a valid request", async (t) => { - const request = prepareRequest({ - text: "foo", - PALM_KEY: "bar", - }); - t.is( - request.url, - "https://generativelanguage.googleapis.com/v1beta2/models/text-bison-001:generateText?key=bar" - ); - t.is(request.method, "POST"); - t.is(request.headers.get("Content-Type"), "application/json"); - t.is(await request.text(), JSON.stringify({ prompt: { text: "foo" } })); -}); - -test("prepareRequest knows how to handle stop sequences", async (t) => { - const request = prepareRequest({ - text: "foo", - PALM_KEY: "bar", - stopSequences: ["baz"], - }); - t.is( - request.url, - "https://generativelanguage.googleapis.com/v1beta2/models/text-bison-001:generateText?key=bar" - ); - t.is(request.method, "POST"); - t.is(request.headers.get("Content-Type"), "application/json"); - t.is( - await request.text(), - JSON.stringify({ - prompt: { text: "foo" }, - stopSequences: ["baz"], - }) - ); -}); - -test("prepareRequest knows how to handle safety settings", async (t) => { - const request = prepareRequest({ - text: "foo", - PALM_KEY: "bar", - safetySettings: [ - { - category: "HARM_CATEGORY_DEROGATORY", - threshold: "BLOCK_LOW_AND_ABOVE", - }, - ], - }); - t.is( - request.url, - "https://generativelanguage.googleapis.com/v1beta2/models/text-bison-001:generateText?key=bar" - ); - t.is(request.method, "POST"); - t.is(request.headers.get("Content-Type"), "application/json"); - t.is( - await request.text(), - JSON.stringify({ - prompt: { text: "foo" }, - safetySettings: [ - { - category: "HARM_CATEGORY_DEROGATORY", - threshold: "BLOCK_LOW_AND_ABOVE", - }, - ], - }) - ); -}); - -test("prepareResponse returns a valid response", async (t) => { - const data = new Response( - JSON.stringify({ - candidates: [{ output: "foo" }], - }) - ); - const response = await prepareResponse(data); - t.deepEqual(response, { completion: "foo", candidates: [{ output: "foo" }] }); -}); - -test("prepareResponse returns an error response is blocked", async (t) => { - const data = new Response( - JSON.stringify({ - filters: [{ reason: "foo" }], - }) - ); - const response = await prepareResponse(data); - t.deepEqual(response, { - $error: { - kind: "error", - error: new Error( - 'Palm generateText failed: {"filters":[{"reason":"foo"}]}' - ), - filters: [{ reason: "foo" }], - status: 200, - }, - }); -}); diff --git a/packages/palm-kit/tsconfig.json b/packages/palm-kit/tsconfig.json deleted file mode 100644 index 1ff943cd641..00000000000 --- a/packages/palm-kit/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "outDir": "./dist" - }, - "include": ["src/**/*", "tests/**/*"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/python-wasm/.eslintrc b/packages/python-wasm/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/python-wasm/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/python-wasm/CHANGELOG.md b/packages/python-wasm/CHANGELOG.md deleted file mode 100644 index 2f2133c27e8..00000000000 --- a/packages/python-wasm/CHANGELOG.md +++ /dev/null @@ -1,81 +0,0 @@ -# @breadboard-ai/python-wasm - -## 0.1.6 - -### Patch Changes - -- 54c8197: Make build API kit function async -- Updated dependencies [49e2740] -- Updated dependencies [54c8197] -- Updated dependencies [2f1b85c] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [2fa05f0] -- Updated dependencies [f71bcfb] -- Updated dependencies [3188607] -- Updated dependencies [8540b93] -- Updated dependencies [8330f0c] -- Updated dependencies [1423647] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [91fe8bb] -- Updated dependencies [100fc95] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [5834c81] -- Updated dependencies [0ef793f] - - @breadboard-ai/build@0.10.0 - -## 0.1.5 - -### Patch Changes - -- a940b87: Switch to new style of declaring components in kits. -- Updated dependencies [cc5f4b6] -- Updated dependencies [a940b87] -- Updated dependencies [374ea85] -- Updated dependencies [f93ec06] -- Updated dependencies [398bf4f] -- Updated dependencies [7de241c] - - @breadboard-ai/build@0.9.0 - -## 0.1.4 - -### Patch Changes - -- 9a2ffab: Unpin @breadboard-ai/build dependency from being overly constrained -- b049e00: Convert to simpler kit function -- Updated dependencies [ad8aa22] -- Updated dependencies [f78ec0a] -- Updated dependencies [2312443] -- Updated dependencies [b76f9a1] -- Updated dependencies [15ae381] - - @breadboard-ai/build@0.8.0 - -## 0.1.3 - -### Patch Changes - -- Updated dependencies [da43bb5] -- Updated dependencies [5cf08f1] -- Updated dependencies [9d93cf8] -- Updated dependencies [26e1099] - - @breadboard-ai/build@0.7.1 - -## 0.1.2 - -### Patch Changes - -- 29774aa: Update dependency package versions. - -## 0.1.1 - -### Patch Changes - -- Updated dependencies [00825d5] -- Updated dependencies [14853d5] -- Updated dependencies [6ada218] -- Updated dependencies [2ace620] -- Updated dependencies [c5f8e4f] -- Updated dependencies [06c3f57] - - @breadboard-ai/build@0.7.0 diff --git a/packages/python-wasm/README.md b/packages/python-wasm/README.md deleted file mode 100644 index 51b6b4ec116..00000000000 --- a/packages/python-wasm/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Breadboard Python wasm - -[![Published on npm](https://img.shields.io/npm/v/@breadboard-ai/python-wasm.svg?logo=npm)](https://www.npmjs.com/package/@breadboard-ai/python-wasm) - -This provides an implementation of a `runPython` component, backed by wasm ([WebAssembly](https://webassembly.org/)) diff --git a/packages/python-wasm/package.json b/packages/python-wasm/package.json deleted file mode 100644 index e81f1d98ed7..00000000000 --- a/packages/python-wasm/package.json +++ /dev/null @@ -1,128 +0,0 @@ -{ - "name": "@breadboard-ai/python-wasm", - "version": "0.1.6", - "description": "A runPython Breadboard node which uses WASM (Web Assembly)", - "license": "Apache-2.0", - "author": "Google LLC", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/build#readme", - "repository": { - "directory": "packages/build", - "type": "git", - "url": "git+https://github.com/breadboard-ai/python-wasm.git" - }, - "type": "module", - "main": "dist/index.js", - "typings": "dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "./index.js": { - "types": null, - "default": null - }, - "./internal/*.js": { - "types": "./dist/internal/*.d.ts", - "default": null - }, - "./*.js": { - "types": "./dist/*.d.ts", - "default": "./dist/*.js" - } - }, - "files": [ - "dist/**/*.{js,js.map,d.ts}", - "!dist/test/", - "CHANGELOG.md" - ], - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "build:tsc": "wireit", - "test": "wireit", - "test:only": "wireit", - "coverage": "wireit", - "lint": "wireit", - "test-and-lint": "wireit", - "dev": "npm run test-and-lint --watch" - }, - "wireit": { - "build": { - "dependencies": [ - "build:tsc", - "../build:build" - ] - }, - "build:tsc": { - "command": "tsc --pretty", - "dependencies": [ - "../build:build:tsc" - ], - "files": [ - "src/", - "tsconfig.json", - "package.json" - ], - "output": [ - "dist/" - ], - "clean": "if-file-deleted" - }, - "test": { - "command": "node --test --test-reporter spec dist/test/*_test.js", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "test:only": { - "command": "node --test --test-only --enable-source-maps --test-reporter spec dist/test/*_test.js", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [] - }, - "coverage": { - "command": "node --test --enable-source-maps --experimental-test-coverage --test-reporter lcov --test-reporter-destination=lcov.info dist/test/*_test.js", - "dependencies": [ - "build:tsc" - ], - "files": [], - "output": [ - "lcov.info" - ] - }, - "lint": { - "command": "eslint src/ --ext .ts", - "dependencies": [ - "build:tsc" - ], - "files": [ - ".eslintrc", - "../../.eslintrc.json" - ], - "output": [] - }, - "test-and-lint": { - "dependencies": [ - "test", - "lint" - ] - } - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "pyodide": "^0.26.2" - }, - "devDependencies": { - "eslint": "^8.57.1", - "typescript": "^5.6.2", - "wireit": "^0.14.9" - } -} diff --git a/packages/python-wasm/src/index.ts b/packages/python-wasm/src/index.ts deleted file mode 100644 index 9aa0aa984ca..00000000000 --- a/packages/python-wasm/src/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { kit } from "@breadboard-ai/build"; -import { runPython } from "./run-python.js"; - -export default await kit({ - title: "Python Wasm Kit", - description: "An example kit", - version: "0.1.0", - url: "npm:@breadboard-ai/python-wasm", - components: { runPython }, -}); diff --git a/packages/python-wasm/src/run-python.ts b/packages/python-wasm/src/run-python.ts deleted file mode 100644 index 5e00ac1b4bb..00000000000 --- a/packages/python-wasm/src/run-python.ts +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { defineNodeType } from "@breadboard-ai/build"; -import { loadPyodide } from "pyodide"; - -export const runPython = defineNodeType({ - name: "runPython", - inputs: { - $code: { - type: "string", - description: "The Python code to run", - format: "multiline", - }, - "*": { - type: "unknown", - }, - }, - outputs: { - "*": { - type: "unknown", - }, - }, - - describe: () => { - // TODO(aomarks) Allowing passing in input/output schemas so that we can - // show the proper ports. - return { - inputs: { "*": "unknown" }, - outputs: { "*": "unknown" }, - }; - }, - - invoke: async ({ $code }, inputs) => { - // Load the Python WASM runtime. - let pyodie: Awaited>; - try { - pyodie = await loadPyodide(); - } catch (e) { - return { - $error: `Error loading pyodide: ${e} ${(e as Error).stack}`, - }; - } - - // Invoke user code in the Python WASM runtime. - let rawResult: unknown; - try { - pyodie.globals.set("inputs", inputs); - rawResult = await pyodie.runPythonAsync($code); - } catch (e) { - return { - $error: `Error executing Python: ${e} ${(e as Error).stack}`, - }; - } - - // Convert Python proxy value to a JavaScript value using - // https://pyodide.org/en/stable/usage/api/js-api.html#pyodide.ffi.PyProxy.toJs - if (typeof rawResult !== "object" || rawResult === null) { - return { - $error: - `Python function did not return a dict.` + - ` Got type "${niceType(rawResult)}".` + - ` Please return a dict with JSON serializable values.`, - }; - } - if (!("toJs" in rawResult)) { - return { - $error: - `Python function returned an object which` + - ` cannot be converted to a JavaScript value.` + - ` Please return a dict with JSON serializable values.`, - }; - } - let jsResult: unknown; - try { - jsResult = (rawResult as { toJs: () => unknown }).toJs(); - } catch (e) { - return { - $error: - `Error converting Python value to JavaScript value: ${e}` + - ` Please return a dict with JSON serializable values.`, - }; - } - - // Ensure that the JavaScript value we ended up with is a JSON-serializable - // object, and also convert it to a plain object because the result we get - // from toJs() will still be a special pyoide type which is not - // structuredClone. - let jsonSafeResult: unknown; - try { - jsonSafeResult = JSON.parse(JSON.stringify(jsResult)); - } catch (e) { - return { - $error: - `Error serializing Python value to JSON: ${e}.` + - ` Please return a dict with JSON serializable values.`, - }; - } - if ( - !( - typeof jsonSafeResult === "object" && - jsonSafeResult !== null && - jsonSafeResult.constructor === Object - ) - ) { - // This handles the Array case (which would have constructor === Array - // instead of Object), and possibly some other weird cases. - return { - $error: - `Python function did not return a dict.` + - ` Got type "${niceType(jsonSafeResult)}".` + - ` Please return a dict with JSON serializable values.`, - }; - } - - // Done! - return jsonSafeResult; - }, -}); - -/** - * Just `typeof`, but with a special case for `null` and `array` (which would - * otherwise both be `"object"`). - */ -function niceType( - value: unknown -): - | "null" - | "array" - | "string" - | "number" - | "bigint" - | "boolean" - | "symbol" - | "undefined" - | "object" - | "function" { - if (value === null) { - return "null"; - } - if (Array.isArray(value)) { - return "array"; - } - return typeof value; -} diff --git a/packages/python-wasm/src/test/run-python_test.ts b/packages/python-wasm/src/test/run-python_test.ts deleted file mode 100644 index 6fc288b9432..00000000000 --- a/packages/python-wasm/src/test/run-python_test.ts +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import assert from "node:assert/strict"; -import { test } from "node:test"; -import { runPython } from "../run-python.js"; - -test("can run some python with various types", async () => { - const result = await runPython.invoke( - { - $code: ` -{ - "sum": inputs.num + len(inputs.str) + 3, - "arr": ["foo", 123, True], - "obj": {"foo": 123} -}`, - num: 1, - str: "ab", - }, - null as never - ); - assert.deepEqual(result, { - sum: 6, - arr: ["foo", 123, true], - obj: { foo: 123 }, - }); -}); - -test("errors on python exception", async () => { - const result = await runPython.invoke( - { $code: `raise Exception("foo")` }, - null as never - ); - const message = (result?.$error as { error?: { message?: string } }).error - ?.message; - assert.match( - message ?? "", - /^Error executing Python: PythonError: Traceback/ - ); -}); - -test("errors if string returned instead of dict", async () => { - const result = await runPython.invoke({ $code: `"foo"` }, null as never); - assert.deepEqual(result, { - $error: { - kind: "error", - error: { - message: - `Python function did not return a dict. ` + - `Got type "string". Please return a dict with JSON serializable values.`, - }, - }, - }); -}); - -test("errors if array returned instead of dict", async () => { - const result = await runPython.invoke({ $code: `["foo"]` }, null as never); - assert.deepEqual(result, { - $error: { - kind: "error", - error: { - message: - `Python function did not return a dict. ` + - `Got type "array". Please return a dict with JSON serializable values.`, - }, - }, - }); -}); - -test("default schema", async () => { - const desc = await runPython.describe({}, null as never); - assert.deepEqual(desc, { - inputSchema: { - type: "object", - properties: { - $code: { - title: "$code", - description: "The Python code to run", - format: "multiline", - type: "string", - }, - }, - required: ["$code"], - additionalProperties: true, - }, - outputSchema: { - type: "object", - properties: {}, - required: [], - additionalProperties: true, - }, - }); -}); diff --git a/packages/python-wasm/tsconfig.json b/packages/python-wasm/tsconfig.json deleted file mode 100644 index 4c0109444dd..00000000000 --- a/packages/python-wasm/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "rootDir": "src", - "outDir": "dist", - "tsBuildInfoFile": "dist/.tsbuildinfo", - "target": "ES2022", - "module": "NodeNext", - "moduleResolution": "NodeNext", - "types": ["node"], - "lib": ["ES2022", "DOM"], - "incremental": true, - "declaration": true, - "sourceMap": true, - "inlineSources": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "noImplicitOverride": true, - "noUncheckedIndexedAccess": true, - "verbatimModuleSyntax": true, - "useUnknownInCatchVariables": true - }, - "include": ["src/**/*.ts"], - "exclude": [] -} diff --git a/packages/remote-board-server/.eslintrc b/packages/remote-board-server/.eslintrc deleted file mode 100644 index f72cccfe73a..00000000000 --- a/packages/remote-board-server/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"] - } -} diff --git a/packages/remote-board-server/.gitignore b/packages/remote-board-server/.gitignore deleted file mode 100644 index c819d9232a7..00000000000 --- a/packages/remote-board-server/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# pyodide assets that we copy into public/. We don't want to check these in -# because they come from NPM. -public/pyodide* -public/python* \ No newline at end of file diff --git a/packages/remote-board-server/CHANGELOG.md b/packages/remote-board-server/CHANGELOG.md deleted file mode 100644 index 2cdb98196ab..00000000000 --- a/packages/remote-board-server/CHANGELOG.md +++ /dev/null @@ -1,90 +0,0 @@ -# @breadboard-ai/remote-board-server - -## 1.17.0 - -### Minor Changes - -- 157c31e: Implement remote board server -- 60349b8: Add board server management and remote board server packages - -### Patch Changes - -- Updated dependencies [49e2740] -- Updated dependencies [323216f] -- Updated dependencies [54c8197] -- Updated dependencies [f94f498] -- Updated dependencies [703f17d] -- Updated dependencies [8d06f3c] -- Updated dependencies [6136d87] -- Updated dependencies [0273985] -- Updated dependencies [f5d3111] -- Updated dependencies [cb8c99a] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [8f9fddf] -- Updated dependencies [2fa05f0] -- Updated dependencies [4e0a4f6] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [f71bcfb] -- Updated dependencies [a104fa7] -- Updated dependencies [f0b5ccc] -- Updated dependencies [8a1b8c4] -- Updated dependencies [3188607] -- Updated dependencies [58d2e8c] -- Updated dependencies [9797718] -- Updated dependencies [679719b] -- Updated dependencies [88298d5] -- Updated dependencies [b673bfa] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [feeed7a] -- Updated dependencies [4cc71ee] -- Updated dependencies [8330f0c] -- Updated dependencies [9b62fc2] -- Updated dependencies [a039d2e] -- Updated dependencies [e63b5dd] -- Updated dependencies [1423647] -- Updated dependencies [74d50d4] -- Updated dependencies [9783ba8] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [9ce8ad3] -- Updated dependencies [7fdf9c2] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [91fe8bb] -- Updated dependencies [e38bf19] -- Updated dependencies [100fc95] -- Updated dependencies [4423c35] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [78d6394] -- Updated dependencies [5834c81] -- Updated dependencies [d7606d3] -- Updated dependencies [0ef793f] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] -- Updated dependencies [9c04caa] -- Updated dependencies [e026112] -- Updated dependencies [94759f7] -- Updated dependencies [281ab28] -- Updated dependencies [e74ee2f] -- Updated dependencies [5fc6e8b] - - @breadboard-ai/build@0.10.0 - - @google-labs/gemini-kit@0.8.0 - - @google-labs/core-kit@0.15.0 - - @google-labs/json-kit@0.3.8 - - @google-labs/agent-kit@0.12.0 - - @google-labs/breadboard@0.27.0 - - @google-labs/breadboard-schema@1.8.0 - - @google-labs/template-kit@0.3.10 - - @google-labs/node-nursery-web@1.3.2 - - @breadboard-ai/data-store@0.2.3 - - @google-labs/palm-kit@0.1.4 diff --git a/packages/remote-board-server/README.md b/packages/remote-board-server/README.md deleted file mode 100644 index 17bfc2a30f9..00000000000 --- a/packages/remote-board-server/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Remote Board Server - -A Board Server implementation backed by a remote source. diff --git a/packages/remote-board-server/package.json b/packages/remote-board-server/package.json deleted file mode 100644 index 9a1f86497db..00000000000 --- a/packages/remote-board-server/package.json +++ /dev/null @@ -1,115 +0,0 @@ -{ - "name": "@breadboard-ai/remote-board-server", - "version": "1.17.0", - "description": "Remote Board Server for Breadboard", - "main": "./dist/index.js", - "exports": { - ".": { - "default": "./dist/index.js", - "types": "./dist/index.d.ts" - } - }, - "types": "dist/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "build:tsc": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "../breadboard:build", - "../build:build", - "../data-store:build", - "../schema:build", - "../agent-kit:build", - "../core-kit:build", - "../google-drive-kit:build", - "../json-kit:build", - "../template-kit:build", - "../palm-kit:build", - "build:tsc" - ] - }, - "typescript-files-and-deps": { - "dependencies": [ - "../breadboard:build:tsc", - "../build:build:tsc", - "../data-store:build:tsc", - "../schema:build:tsc", - "../agent-kit:build:tsc", - "../core-kit:build:tsc", - "../google-drive-kit:build:tsc", - "../json-kit:build:tsc", - "../template-kit:build:tsc", - "../palm-kit:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "typescript-files-and-deps" - ], - "files": [], - "output": [ - "dist/", - "!dist/**/*.min.js{,.map}" - ], - "clean": "if-file-deleted" - } - }, - "repository": { - "directory": "packages/remote-board-server", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/" - ], - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/remote-board-server#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@google-labs/tsconfig": "^0.0.1", - "@types/markdown-it": "^14.1.2", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "dotenv": "^16.4.5", - "tsx": "^4.19.1", - "typescript": "^5.6.2", - "vite": "^5.4.8", - "vite-plugin-full-reload": "^1.2.0", - "vite-plugin-watch-and-run": "^1.7.0", - "vitest": "^2.1.1" - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/data-store": "^0.2.3", - "@google-labs/agent-kit": "^0.12.0", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/breadboard-schema": "^1.8.0", - "@google-labs/core-kit": "^0.15.0", - "@google-labs/gemini-kit": "^0.8.0", - "@google-labs/json-kit": "^0.3.8", - "@google-labs/node-nursery-web": "^1.3.2", - "@google-labs/palm-kit": "^0.1.4", - "@google-labs/template-kit": "^0.3.10" - } -} diff --git a/packages/remote-board-server/src/index.ts b/packages/remote-board-server/src/index.ts deleted file mode 100644 index 82f217abc55..00000000000 --- a/packages/remote-board-server/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export { RemoteBoardServer } from "./remote-board-server.js"; diff --git a/packages/remote-board-server/src/remote-board-server.ts b/packages/remote-board-server/src/remote-board-server.ts deleted file mode 100644 index fbc1fa9d5a9..00000000000 --- a/packages/remote-board-server/src/remote-board-server.ts +++ /dev/null @@ -1,435 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - blankLLMContent, - type BoardServer, - type BoardServerCapabilities, - type BoardServerConfiguration, - type BoardServerExtension, - type BoardServerProject, - type ChangeNotificationCallback, - type GraphDescriptor, - type GraphProviderCapabilities, - type GraphProviderExtendedCapabilities, - type GraphProviderItem, - type GraphProviderStore, - type Kit, - type Permission, - type User, -} from "@google-labs/breadboard"; -import { loadKits } from "./utils/kit-loader"; -import GeminiKit from "@google-labs/gemini-kit"; -import PythonWasmKit from "@breadboard-ai/python-wasm"; -import GoogleDriveKit from "@breadboard-ai/google-drive-kit"; - -// TODO: Get these kits from each board server. -const loadedKits = loadKits([ - GeminiKit, - // TODO: BuildExampleKit, - PythonWasmKit, - GoogleDriveKit, -]); - -/** - * For now, make a flag that controls whether to use simple requests or not. - * Simple requests use "API_KEY" query parameter for authentication. - */ -const USE_SIMPLE_REQUESTS = true; -const CONTENT_TYPE = { "Content-Type": "application/json" }; - -const authHeader = (apiKey: string, headers?: HeadersInit) => { - const h = new Headers(headers); - h.set("Authorization", `Bearer ${apiKey}`); - return h; -}; - -const createRequest = ( - url: URL | string, - apiKey: string | null, - method: string, - body?: unknown -) => { - if (typeof url === "string") { - url = new URL(url, window.location.href); - } - if (USE_SIMPLE_REQUESTS) { - if (apiKey) { - url.searchParams.set("API_KEY", apiKey); - } - return new Request(url.href, { - method, - credentials: "include", - body: JSON.stringify(body), - }); - } - - return new Request(url, { - method, - credentials: "include", - headers: apiKey ? authHeader(apiKey, CONTENT_TYPE) : CONTENT_TYPE, - body: JSON.stringify(body), - }); -}; - -export class RemoteBoardServer extends EventTarget implements BoardServer { - public readonly url: URL; - public readonly kits: Kit[]; - public readonly users: User[]; - public readonly secrets = new Map(); - public readonly extensions: BoardServerExtension[] = []; - public readonly capabilities: BoardServerCapabilities; - - projects: Promise; - - static readonly PROTOCOL = "https://"; - - static parseURL(url: string) { - if (!url.startsWith(this.PROTOCOL)) { - throw new Error(`Not a local store URL: ${url}`); - } - - return url.replace(/^idb:\/\//, ""); - } - - static async from(url: string, user: User) { - try { - const configuration = { - url: new URL(url), - projects: Promise.resolve([]), - kits: await loadedKits, - users: [], - secrets: new Map(), - extensions: [], - capabilities: { - connect: true, - disconnect: true, - refresh: true, - watch: false, - preview: true, - }, - }; - - return new RemoteBoardServer(url, configuration, user); - } catch (err) { - console.warn(err); - return null; - } - } - - constructor( - public readonly name: string, - configuration: BoardServerConfiguration, - public readonly user: User - ) { - super(); - - this.url = configuration.url; - this.projects = this.#refreshProjects(); - this.kits = configuration.kits; - this.users = configuration.users; - this.secrets = configuration.secrets; - this.extensions = configuration.extensions; - this.capabilities = configuration.capabilities; - } - - // This is a workaround for items() being sync. Since we expect ready() to be - // awaited we know #projects will be populated by the time items() is called. - #projects: BoardServerProject[] = []; - async ready(): Promise { - this.#projects = await this.projects; - } - - async getAccess(url: URL, user: User): Promise { - const project = this.#projects.find((project) => { - return url.pathname.startsWith(project.url.pathname); - }); - - const defaultPermission = { - create: false, - retrieve: false, - update: false, - delete: false, - }; - - if (!project) { - return defaultPermission; - } - - return project.metadata.access.get(user.username) ?? defaultPermission; - } - - isSupported(): boolean { - return true; - } - - canProvide(url: URL): false | GraphProviderCapabilities { - if (!url.href.startsWith(this.url.href)) { - return false; - } - - const project = this.#projects.find((project) => { - return url.pathname.startsWith(project.url.pathname); - }); - - // We recognize it as something that can be loaded from this Board Server, - // but we can't assess the access for it, so assume loading alone is - // acceptable. - if (!project) { - return { - load: true, - save: false, - delete: false, - }; - } - - const access = project.metadata.access.get(this.user.username) ?? { - create: false, - retrieve: true, - update: false, - delete: false, - }; - - return { - load: true, - save: access.update, - delete: access.delete, - }; - } - - extendedCapabilities(): GraphProviderExtendedCapabilities { - return { - modify: true, - connect: true, - disconnect: true, - refresh: true, - watch: false, - preview: true, - }; - } - - async load(url: URL): Promise { - const projects = await this.projects; - const project = projects.find((project) => { - return url.pathname.startsWith(project.url.pathname); - }); - if (!project) { - return null; - } - - if (project.url.href === url.href) { - const request = createRequest(url, null, "GET"); - const response = await fetch(request); - const graph = await response.json(); - return graph; - } - - return null; - } - - async save( - url: URL, - descriptor: GraphDescriptor - ): Promise<{ result: boolean; error?: string }> { - if (!this.canProvide(url)) { - return { result: false }; - } - - const data = await this.#sendToRemote(new URL(url), descriptor); - if (data.error) { - return { result: false, error: data.error }; - } - - this.projects = this.#refreshProjects(); - return { result: true }; - } - - createBlank(url: URL): Promise<{ result: boolean; error?: string }> { - return this.save(url, blankLLMContent()); - } - - async create( - url: URL, - descriptor: GraphDescriptor - ): Promise<{ result: boolean; error?: string }> { - return this.save(url, descriptor); - } - - async delete(url: URL): Promise<{ result: boolean; error?: string }> { - if (!this.canProvide(url)) { - return { result: false }; - } - - try { - const request = createRequest(url, this.user.apiKey, "POST", { - delete: true, - }); - const response = await fetch(request); - const data = await response.json(); - this.projects = this.#refreshProjects(); - - if (data.error) { - return { result: false }; - } - return { result: true }; - } catch (err) { - return { result: true }; - } - } - - connect(_location?: string, _auth?: unknown): Promise { - throw new Error("Method not implemented."); - } - - disconnect(_location: string): Promise { - throw new Error("Method not implemented."); - } - - async refresh(_location: string): Promise { - await this.projects; - return true; - } - - async createURL(location: string, fileName: string): Promise { - const request = createRequest( - `${location}/boards`, - this.user.apiKey, - "POST", - { - name: fileName, - } - ); - const response = await fetch(request); - if (!response.ok) { - return null; - } - const data = await response.json(); - return `${location}/boards/${data.path}`; - } - - parseURL(_url: URL): { location: string; fileName: string } { - throw new Error("Method not implemented."); - } - - async restore(): Promise { - await this.projects; - } - - items(): Map { - const items = new Map(); - const projects: [string, GraphProviderItem][] = []; - - const projectNames = new Set(); - for (const project of this.#projects) { - let title = project.metadata.title ?? "Untitled Board"; - if (projectNames.has(title) && project.url) { - const suffix = new URL(project.url).pathname.split("/").at(-1); - title = `${project.metadata.title ?? "Untitled Board"} [${suffix}]`; - } - - projectNames.add(title); - projects.push([ - title, - { - url: project.url.href, - mine: project.metadata.owner === this.user.username, - readonly: false, - handle: null, - tags: project.metadata?.tags, - username: project.metadata.owner, - }, - ]); - } - - items.set(this.name, { - items: new Map(projects), - permission: "granted", - title: this.name, - }); - - return items; - } - - startingURL(): URL | null { - return null; - } - - watch(_callback: ChangeNotificationCallback): void { - throw new Error("Method not implemented."); - } - - async preview(url: URL): Promise { - return new URL(url.href.replace(/json$/, "app")); - } - - async #sendToRemote(url: URL, descriptor: GraphDescriptor) { - if (!this.user.apiKey) { - return { error: "No API Key" }; - } - const request = createRequest(url, this.user.apiKey, "POST", descriptor); - const response = await fetch(request); - return await response.json(); - } - - async #refreshProjects(): Promise { - type BoardServerListingItem = GraphProviderItem & { - path: string; - }; - - const projects: BoardServerProject[] = []; - try { - const request = createRequest( - `${this.url.origin}/boards`, - this.user.apiKey, - "GET" - ); - - const response = await fetch(request); - const files: BoardServerListingItem[] = await response.json(); - - for (const item of files) { - // Workaround for the fact that we don't yet store the username as part - // of the Board Server configuration. Here we use the `mine` property to - // set the username. - if (item.mine && item.username) { - this.user.username = item.username; - } - - const canAccess = item.username === this.user.username; - const access = new Map([ - [ - this.user.username, - { - create: canAccess, - retrieve: canAccess, - update: canAccess, - delete: canAccess, - }, - ], - ]); - - const project: BoardServerProject = { - url: new URL(`${this.url.origin}/boards/${item.path}`), - metadata: { - owner: item.username ?? "Unknown", - tags: item.tags, - title: item.title, - access, - }, - }; - - projects.push(project); - } - } catch (err) { - console.warn( - `[Remote Board Server]: Unable to connect to ${this.url}`, - err - ); - } - - return projects; - } -} diff --git a/packages/remote-board-server/src/utils/kit-loader.ts b/packages/remote-board-server/src/utils/kit-loader.ts deleted file mode 100644 index b6f63264465..00000000000 --- a/packages/remote-board-server/src/utils/kit-loader.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { KitConstructor, Kit, asRuntimeKit } from "@google-labs/breadboard"; -import { load } from "@google-labs/breadboard/kits"; - -export const loadKits = async (kitConstructors: KitConstructor[]) => { - const loadedKits = kitConstructors.map((kitConstructor) => - asRuntimeKit(kitConstructor) - ); - - const base = new URL(`${self.location.origin}/kits.json`); - const response = await fetch(base); - const kitList = await response.json(); - - const kits = await Promise.all( - kitList.map(async (kitURL: string) => { - // workaround for vite prod/dev mode difference - if (kitURL.endsWith(".js") && import.meta.env.DEV) { - kitURL = `/src/${kitURL.replace(/\.js$/, ".ts")}`; - } - return await load(new URL(kitURL, base)); - }) - ); - - return [...loadedKits, ...kits]; -}; diff --git a/packages/remote-board-server/tsconfig.json b/packages/remote-board-server/tsconfig.json deleted file mode 100644 index 40a3e9972c4..00000000000 --- a/packages/remote-board-server/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "ESNext", - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - "experimentalDecorators": true, - "useDefineForClassFields": false, - "outDir": "dist", - - /* Bundler mode */ - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": false, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "types": ["vite/client"] - }, - "include": ["src/**/*.ts", "tests/**/*.ts"], - "extends": "@google-labs/tsconfig/base.json" -} diff --git a/packages/schema/.eslintrc b/packages/schema/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/schema/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/schema/CHANGELOG.md b/packages/schema/CHANGELOG.md deleted file mode 100644 index 615fa366394..00000000000 --- a/packages/schema/CHANGELOG.md +++ /dev/null @@ -1,89 +0,0 @@ -# @google-labs/breadboard-schema - -## 1.8.0 - -### Minor Changes - -- 8540b93: Convert Content to Build API and merge Specialist 2 to Specialist. - -### Patch Changes - -- 8d06f3c: Introduce GraphMetadata.visual.window. - -## 1.7.0 - -### Minor Changes - -- c397d53: Add support for multiple graph entry points and start tags. - -## 1.6.0 - -### Minor Changes - -- 2312443: Add support for `deprecated` and `experimental` tags on Kits. - -## 1.5.1 - -### Patch Changes - -- dd783e0: Add analyzeIsJsonSubSchema function -- 3aba1a4: Improve subschema checking of properties and additionalProperties - -## 1.5.0 - -### Minor Changes - -- 7af14cf: Add support for comment nodes -- 511bd9b: Add `tags` to `GraphMetadata`. -- 431fa3d: Add support for website embeds of boards & YouTube videos - -### Patch Changes - -- 3d7b4a7: Introduce optional `help` metadata for graphs and kits. -- cd73b17: Switch to Nodejs v20.14.0 as the baseline. -- fcef799: Update `help` to have description and URL - -## 1.4.1 - -### Patch Changes - -- 416aed2: Introduce `metadata` for `NodeHandler` entries, teaching node types in Kits to describe themselves. - -## 1.4.0 - -### Minor Changes - -- f005b3b: Introduce `load` API for kits. -- 9b8e732: replace schema with version generated from TS source -- efeb1a3: Add `NodeMetadata.visual` field. - -### Patch Changes - -- 4a4a1f6: Place unfinished sidecar events at the bottom of the event list. -- eabd97b: Introduce the concept of log levels in Run Inspector API. - -## 1.3.0 - -### Minor Changes - -- ee00249: Introduce `NodeMetadata`. -- 5a65297: Add TypeScript types for Breadboard graphs in schema package - -## 1.2.0 - -### Minor Changes - -- e7be365: add json export to schema package -- f6a7f43: Add schemas to serialised boards - -## 1.1.0 - -### Minor Changes - -- 3972f17: correct schema ID and update plumbing - -## 1.0.0 - -### Major Changes - -- 6e8c08d: initial independent version of schema diff --git a/packages/schema/README.md b/packages/schema/README.md deleted file mode 100644 index 37c1d113ce2..00000000000 --- a/packages/schema/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Breadboard Schema - -A tool that generates a JSON schema from the Breadboard TypeScript types. diff --git a/packages/schema/breadboard.schema.json b/packages/schema/breadboard.schema.json deleted file mode 100644 index a93b09602f1..00000000000 --- a/packages/schema/breadboard.schema.json +++ /dev/null @@ -1,538 +0,0 @@ -{ - "$id": "https://raw.githubusercontent.com/breadboard-ai/breadboard/@google-labs/breadboard-schema@1.8.0/packages/schema/breadboard.schema.json", - "$schema": "http://json-schema.org/draft-07/schema#", - "$ref": "#/definitions/GraphDescriptor", - "definitions": { - "GraphDescriptor": { - "type": "object", - "additionalProperties": false, - "properties": { - "inputs": { - "$ref": "#/definitions/InputValues", - "description": "For internal testing only. Do not use.", - "deprecated": "For internal testing only. Do not use." - }, - "outputs": { - "anyOf": [ - { - "$ref": "#/definitions/OutputValues" - }, - { - "type": "array", - "items": { - "$ref": "#/definitions/OutputValues" - } - } - ], - "description": "For internal testing only. Do not use.", - "deprecated": "For internal testing only. Do not use." - }, - "sequence": { - "type": "array", - "items": { - "$ref": "#/definitions/NodeIdentifier" - }, - "description": "For internal testing only. Do not use.", - "deprecated": "For internal testing only. Do not use." - }, - "throws": { - "type": "boolean", - "description": "For internal testing only. Do not use.", - "deprecated": "For internal testing only. Do not use." - }, - "safe": { - "type": "boolean", - "description": "For internal testing only. Do not use.", - "deprecated": "For internal testing only. Do not use." - }, - "expectedLabels": { - "type": "array", - "items": { - "type": "array", - "items": { - "type": "string" - } - }, - "description": "For internal testing only. Do not use.", - "deprecated": "For internal testing only. Do not use." - }, - "explanation": { - "type": "string", - "description": "For internal testing only. Do not use.", - "deprecated": "For internal testing only. Do not use." - }, - "start": { - "$ref": "#/definitions/StartLabel", - "description": "For internal testing only. Do not use.", - "deprecated": "For internal testing only. Do not use." - }, - "metadata": { - "$ref": "#/definitions/GraphMetadata", - "description": "Metadata associated with the graph." - }, - "edges": { - "type": "array", - "items": { - "$ref": "#/definitions/Edge" - }, - "description": "The collection of all edges in the graph." - }, - "nodes": { - "type": "array", - "items": { - "$ref": "#/definitions/NodeDescriptor" - }, - "description": "The collection of all nodes in the graph." - }, - "kits": { - "type": "array", - "items": { - "$ref": "#/definitions/KitDescriptor" - }, - "description": "All the kits (collections of node handlers) that are used by the graph." - }, - "graphs": { - "$ref": "#/definitions/SubGraphs", - "description": "Sub-graphs that are also described by this graph representation." - }, - "args": { - "$ref": "#/definitions/InputValues", - "description": "Arguments that are passed to the graph, useful to bind values to graphs." - }, - "$schema": { - "type": "string", - "description": "The schema of the graph." - }, - "url": { - "type": "string", - "description": "The URL pointing to the location of the graph. This URL is used to resolve relative paths in the graph. If not specified, the paths are assumed to be relative to the current working directory." - }, - "title": { - "type": "string", - "description": "The title of the graph." - }, - "description": { - "type": "string", - "description": "The description of the graph." - }, - "version": { - "type": "string", - "description": "Version of the graph. [semver](https://semver.org/) format is encouraged." - } - }, - "required": [ - "edges", - "nodes" - ], - "description": "Represents a graph." - }, - "InputValues": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/NodeValue" - }, - "propertyNames": { - "description": "Unique identifier of a node's input." - }, - "description": "Values that are supplied as inputs to the `NodeHandler`." - }, - "NodeValue": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - }, - { - "not": {} - }, - { - "type": "array", - "items": { - "$ref": "#/definitions/NodeValue" - } - }, - { - "$ref": "#/definitions/Capability" - }, - { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/NodeValue" - } - } - ], - "description": "A type representing a valid JSON value." - }, - "Capability": { - "type": "object", - "properties": { - "kind": { - "type": "string" - } - }, - "required": [ - "kind" - ], - "additionalProperties": false - }, - "OutputValues": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/NodeValue" - }, - "description": "Values that the `NodeHandler` outputs." - }, - "NodeIdentifier": { - "type": "string", - "description": "Unique identifier of a node in a graph." - }, - "StartLabel": { - "type": "string", - "enum": [ - "default", - "describe" - ], - "description": "Valid start labels." - }, - "GraphMetadata": { - "type": "object", - "properties": { - "icon": { - "type": "string", - "description": "The icon that identifies the graph. Can be a URL or a Material Design id." - }, - "comments": { - "type": "array", - "items": { - "$ref": "#/definitions/CommentNode" - } - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/GraphTag" - }, - "description": "Tags associated with the graph. At this moment, free-form strings." - }, - "help": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "url": { - "type": "string" - } - }, - "required": [ - "url" - ], - "additionalProperties": false, - "description": "The documentation for the graph, expressed as a URL and optional description." - }, - "describer": { - "type": "string", - "description": "The URL of the graph that will act as the describer for this graph. Can be a relative URL and refer to a sub-graph within this graph." - }, - "visual": { - "type": "object", - "properties": { - "window": { - "type": "object", - "properties": { - "x": { - "type": "number" - }, - "y": { - "type": "number" - }, - "width": { - "type": "number" - }, - "height": { - "type": "number" - } - }, - "required": [ - "x", - "y", - "width", - "height" - ], - "additionalProperties": false, - "description": "Last known position of the graph in the editor." - } - }, - "additionalProperties": false, - "description": "The metadata associated with the visual representation of the graph." - } - }, - "additionalProperties": { - "$ref": "#/definitions/NodeValue" - }, - "description": "Represents graph metadata." - }, - "CommentNode": { - "type": "object", - "properties": { - "id": { - "$ref": "#/definitions/NodeIdentifier", - "description": "Unique id of the comment node in graph metadata." - }, - "text": { - "type": "string", - "description": "The text content of the comment." - }, - "metadata": { - "$ref": "#/definitions/NodeMetadata", - "description": "The metadata of the comment node. Use this to provide additional information about the comment node." - } - }, - "required": [ - "id", - "text" - ], - "additionalProperties": false - }, - "NodeMetadata": { - "type": "object", - "properties": { - "title": { - "type": "string", - "description": "The title of the node." - }, - "description": { - "type": "string", - "description": "A more detailed description of the node." - }, - "visual": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - }, - { - "type": "array", - "items": { - "$ref": "#/definitions/NodeValue" - } - }, - { - "$ref": "#/definitions/Capability" - }, - { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/NodeValue" - } - } - ], - "description": "Metadata that conveys visual information about the node. Can be used by visual editors to store information about the node's appearance, current position, etc." - }, - "logLevel": { - "type": "string", - "enum": [ - "debug", - "info" - ], - "description": "Logging level." - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/NodeTag" - }, - "description": "Tags associated with the node. Can be either a string or a structured tag, like a `StartTag`." - } - }, - "additionalProperties": false, - "description": "Represents metadata of a node. This is an optional part of the `NodeDescriptor` that can be used to provide additional information about the node." - }, - "NodeTag": { - "anyOf": [ - { - "type": "string", - "const": "start" - }, - { - "$ref": "#/definitions/StartTag" - } - ], - "description": "Represents a tag that can be associated with a node." - }, - "StartTag": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "start" - }, - "label": { - "$ref": "#/definitions/StartLabel" - } - }, - "required": [ - "type" - ], - "additionalProperties": false, - "description": "Represents a start tag, which is a special tag that can be associated with a node. It is used to indicate that the node is a starting point for traversal. The `label` field allows the user to specify additional way to specify the kind of traversal they are looking for." - }, - "GraphTag": { - "type": "string", - "enum": [ - "published", - "tool", - "experimental" - ], - "description": "A tag that can be associated with a graph.\n- `published`: The graph is published (as opposed to a draft). It may be used in production and shared with others.\n- `tool`: The graph is intended to be a tool.\n- `experimental`: The graph is experimental and may not be stable." - }, - "Edge": { - "type": "object", - "properties": { - "from": { - "$ref": "#/definitions/NodeIdentifier", - "description": "The node that the edge is coming from." - }, - "to": { - "$ref": "#/definitions/NodeIdentifier", - "description": "The node that the edge is going to." - }, - "in": { - "$ref": "#/definitions/InputIdentifier", - "description": "The input of the `to` node. If this value is undefined, then the then no data is passed as output of the `from` node." - }, - "out": { - "$ref": "#/definitions/OutputIdentifier", - "description": "The output of the `from` node. If this value is \"*\", then all outputs of the `from` node are passed to the `to` node. If this value is undefined, then no data is passed to any inputs of the `to` node." - }, - "optional": { - "type": "boolean", - "description": "If true, this edge is optional: the data that passes through it is not considered a required input to the node." - }, - "constant": { - "type": "boolean", - "description": "If true, this edge acts as a constant: the data that passes through it remains available even after the node has consumed it." - } - }, - "required": [ - "from", - "to" - ], - "additionalProperties": false, - "description": "Represents an edge in a graph." - }, - "InputIdentifier": { - "type": "string", - "description": "Unique identifier of a node's input." - }, - "OutputIdentifier": { - "type": "string", - "description": "Unique identifier of a node's output." - }, - "NodeDescriptor": { - "type": "object", - "properties": { - "id": { - "$ref": "#/definitions/NodeIdentifier", - "description": "Unique id of the node in graph." - }, - "type": { - "$ref": "#/definitions/NodeTypeIdentifier", - "description": "Type of the node. Used to look up the handler for the node." - }, - "configuration": { - "$ref": "#/definitions/NodeConfiguration", - "description": "Configuration of the node." - }, - "metadata": { - "$ref": "#/definitions/NodeMetadata", - "description": "The metadata of the node. Use this provide additional information about the node." - } - }, - "required": [ - "id", - "type" - ], - "additionalProperties": false, - "description": "Represents a node in a graph." - }, - "NodeTypeIdentifier": { - "type": "string", - "description": "Unique identifier of a node's type." - }, - "NodeConfiguration": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/NodeValue" - }, - "description": "Values that are supplied as part of the graph. These values are merged with the `InputValues` and supplied as inputs to the `NodeHandler`." - }, - "KitDescriptor": { - "type": "object", - "additionalProperties": false, - "properties": { - "title": { - "type": "string", - "description": "The title of the kit." - }, - "description": { - "type": "string", - "description": "The description of the kit." - }, - "version": { - "type": "string", - "description": "Version of the kit. [semver](https://semver.org/) format is encouraged.", - "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/KitTag" - }, - "description": "Tags, associated with the kit." - }, - "url": { - "type": "string", - "description": "The URL pointing to the location of the kit." - } - }, - "required": [ - "url" - ] - }, - "KitTag": { - "type": "string", - "enum": [ - "deprecated", - "experimental" - ], - "description": "Represents various tags that can be associated with a kit.\n- `deprecated`: The kit is deprecated and should not be used.\n- `experimental`: The kit is experimental and may not be stable." - }, - "SubGraphs": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/GraphDescriptor" - }, - "propertyNames": { - "description": "Unique identifier of a graph." - }, - "description": "Represents a collection of sub-graphs. The key is the identifier of the sub-graph. The value is the descriptor of the sub-graph." - } - } -} \ No newline at end of file diff --git a/packages/schema/package.json b/packages/schema/package.json deleted file mode 100644 index 1b48fc9b4a3..00000000000 --- a/packages/schema/package.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "name": "@google-labs/breadboard-schema", - "version": "1.8.0", - "license": "Apache-2.0", - "author": "Google Labs Team", - "repository": { - "directory": "packages/schema", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "publishConfig": { - "registry": "https://wombat-dressing-room.appspot.com" - }, - "files": [ - "CHANGELOG.md", - "dist/graph.{js,js.map,d.ts,d.ts.map}", - "dist/subschema.{js,js.map,d.ts,d.ts.map}", - "breadboard.schema.json" - ], - "type": "module", - "exports": { - ".": "./breadboard.schema.json", - "./breadboard.schema.json": "./breadboard.schema.json", - "./graph.js": { - "import": { - "types": "./dist/graph.d.ts", - "default": "./dist/graph.js" - } - }, - "./subschema.js": { - "import": { - "types": "./dist/subschema.d.ts", - "default": "./dist/subschema.js" - } - } - }, - "scripts": { - "build": "wireit", - "test": "wireit", - "prepack": "wireit", - "build:tsc": "wireit", - "build:schema": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "build:tsc", - "build:schema" - ] - }, - "test": { - "command": "find dist -name '*.test.js' | xargs node --enable-source-maps --test --test-reporter spec", - "dependencies": [ - "build" - ], - "files": [ - "breadboard.schema.json", - "package.json", - "dist/", - "src/tests/**/*.ts" - ] - }, - "prepack": { - "dependencies": [ - "build", - "test" - ] - }, - "build:tsc": { - "command": "tsc --pretty", - "files": [ - "package.json", - "src/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ], - "output": [ - "dist/", - "tsconfig.tsbuildinfo" - ] - }, - "build:schema": { - "command": "node ./dist/scripts/generate-json-schema.js", - "dependencies": [ - "build:tsc" - ], - "files": [ - "package.json", - "src/**/*.ts" - ], - "output": [ - "breadboard.schema.json" - ] - } - }, - "devDependencies": { - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "ts-json-schema-generator": "^2.3.0" - }, - "dependencies": { - "@types/json-schema": "^7.0.15" - } -} diff --git a/packages/schema/src/graph.ts b/packages/schema/src/graph.ts deleted file mode 100644 index b50580e2550..00000000000 --- a/packages/schema/src/graph.ts +++ /dev/null @@ -1,440 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export interface Capability { - readonly kind: string; -} - -/** - * A type representing a valid JSON value. - */ -export type NodeValue = - | string - | number - | boolean - | null - | undefined - | NodeValue[] - | Capability - | { [key: string]: NodeValue }; - -/** - * Unique identifier of a node in a graph. - */ -export type NodeIdentifier = string; - -/** - * Unique identifier of a node's output. - */ -export type OutputIdentifier = string; - -/** - * Unique identifier of a node's input. - */ -export type InputIdentifier = string; - -/** - * Unique identifier of a node's type. - */ -export type NodeTypeIdentifier = string; - -/** - * Represents a node in a graph. - */ -export type NodeDescriptor = { - /** - * Unique id of the node in graph. - */ - id: NodeIdentifier; - - /** - * Type of the node. Used to look up the handler for the node. - */ - type: NodeTypeIdentifier; - - /** - * Configuration of the node. - */ - configuration?: NodeConfiguration; - - /** - * The metadata of the node. - * Use this provide additional information about the node. - */ - metadata?: NodeMetadata; -}; - -export type CommentNode = { - /** - * Unique id of the comment node in graph metadata. - */ - id: NodeIdentifier; - - /** - * The text content of the comment. - */ - text: string; - - /** - * The metadata of the comment node. - * Use this to provide additional information about the comment node. - */ - metadata?: NodeMetadata; -}; - -/** - * Represents an edge in a graph. - */ -export type Edge = { - /** - * The node that the edge is coming from. - */ - from: NodeIdentifier; - - /** - * The node that the edge is going to. - */ - to: NodeIdentifier; - - /** - * The input of the `to` node. If this value is undefined, then - * the then no data is passed as output of the `from` node. - */ - in?: InputIdentifier; - - /** - * The output of the `from` node. If this value is "*", then all outputs - * of the `from` node are passed to the `to` node. If this value is undefined, - * then no data is passed to any inputs of the `to` node. - */ - out?: OutputIdentifier; - - /** - * If true, this edge is optional: the data that passes through it is not - * considered a required input to the node. - */ - optional?: boolean; - - /** - * If true, this edge acts as a constant: the data that passes through it - * remains available even after the node has consumed it. - */ - constant?: boolean; -}; - -/** - * Represents metadata of a node. - * This is an optional part of the `NodeDescriptor` that can be used to - * provide additional information about the node. - */ -export type NodeMetadata = { - /** - * The title of the node. - */ - title?: string; - /** - * A more detailed description of the node. - */ - description?: string; - /** - * Metadata that conveys visual information about the node. Can be used by - * visual editors to store information about the node's appearance, current - * position, etc. - */ - visual?: NodeValue; - /** - * Logging level. - */ - logLevel?: "debug" | "info"; - /** - * Tags associated with the node. Can be either a string or a structured tag, - * like a `StartTag`. - */ - tags?: NodeTag[]; -}; - -/** - * Represents a tag that can be associated with a node. - */ -export type NodeTag = - /** - * A simple start tag, which is the same as { type: "start" }. - */ - | "start" - /** - * A tag that indicates that the node is a starting point for traversal. - */ - | StartTag; - -/** - * Represents a start tag, which is a special tag that can be associated with a - * node. It is used to indicate that the node is a starting point for traversal. - * The `label` field allows the user to specify additional way to specify the - * kind of traversal they are looking for. - */ -export type StartTag = { - type: "start"; - label?: StartLabel; -}; - -/** - * Valid start labels. - */ -export type StartLabel = "default" | "describe"; - -/** - * Represents references to a "kit": a collection of `NodeHandlers`. - * The basic premise here is that people can publish kits with interesting - * handlers, and then graphs can specify which ones they use. - * The `@google-labs/core-kit` package is an example of kit. - */ -export type KitReference = { - /** - * The URL pointing to the location of the kit. - */ - url: string; -}; - -/** - * Represents various tags that can be associated with a kit. - * - `deprecated`: The kit is deprecated and should not be used. - * - `experimental`: The kit is experimental and may not be stable. - */ -export type KitTag = "deprecated" | "experimental"; - -export type KitDescriptor = KitReference & { - /** - * The title of the kit. - */ - title?: string; - /** - * The description of the kit. - */ - description?: string; - /** - * Version of the kit. - * [semver](https://semver.org/) format is encouraged. - * @pattern ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - */ - version?: string; - /** - * Tags, associated with the kit. - */ - tags?: KitTag[]; -}; - -/** - * Describes a light kit: a kit where each node is backed by a graph. - */ -export type KitManifest = KitDescriptor & { - /** - * A map of nodes. Each key in this object is the node that is provided by - * the kit. Each value the `GraphDescriptor` containing the graph. This - * graph will be run (runOnce) when the `invoke` of the node's `NodeHandler` - * is called. - */ - nodes: Record; -}; - -/** - * Represents graph metadata that is stored inline in the GraphDescriptor. - */ -export type GraphInlineMetadata = { - /** - * The schema of the graph. - */ - $schema?: string; - - /** - * The URL pointing to the location of the graph. - * This URL is used to resolve relative paths in the graph. - * If not specified, the paths are assumed to be relative to the current - * working directory. - */ - url?: string; - /** - * The title of the graph. - */ - title?: string; - /** - * The description of the graph. - */ - description?: string; - /** - * Version of the graph. - * [semver](https://semver.org/) format is encouraged. - */ - version?: string; -}; - -/** - * A tag that can be associated with a graph. - * - `published`: The graph is published (as opposed to a draft). It may be - * used in production and shared with others. - * - `tool`: The graph is intended to be a tool. - * - `experimental`: The graph is experimental and may not be stable. - */ -export type GraphTag = "published" | "tool" | "experimental"; - -/** - * Represents graph metadata. - */ -export type GraphMetadata = { - /** - * The icon that identifies the graph. Can be a URL or a Material Design id. - */ - icon?: string; - [name: string]: NodeValue; - comments?: CommentNode[]; - /** - * Tags associated with the graph. At this moment, free-form strings. - */ - tags?: GraphTag[]; - /** - * The documentation for the graph, expressed as a URL and optional description. - */ - help?: { - description?: string; - url: string; - }; - /** - * The URL of the graph that will act as the describer for - * this graph. Can be a relative URL and refer to a sub-graph - * within this graph. - */ - describer?: string; - /** - * The metadata associated with the visual representation of the graph. - */ - visual?: { - /** - * Last known position of the graph in the editor. - */ - window?: { - x: number; - y: number; - width: number; - height: number; - }; - }; -}; - -/** - * Unique identifier of a graph. - */ -export type GraphIdentifier = string; - -/** - * Represents a collection of sub-graphs. - * The key is the identifier of the sub-graph. - * The value is the descriptor of the sub-graph. - */ -export type SubGraphs = Record; - -/** - * Properties used for testing the foundational traversal tests - * These properties are for internal testing only and should not be used. - * @deprecated These properties are for internal testing only and should not be used. - */ -type TestProperties = { - /** - * For internal testing only. Do not use. - * @deprecated For internal testing only. Do not use. - */ - inputs?: InputValues; - - /** - * For internal testing only. Do not use. - * @deprecated For internal testing only. Do not use. - */ - outputs?: OutputValues | OutputValues[]; - - /** - * For internal testing only. Do not use. - * @deprecated For internal testing only. Do not use. - */ - sequence?: NodeIdentifier[]; - - /** - * For internal testing only. Do not use. - * @deprecated For internal testing only. Do not use. - */ - throws?: boolean; - - /** - * For internal testing only. Do not use. - * @deprecated For internal testing only. Do not use. - */ - safe?: boolean; - - /** - * For internal testing only. Do not use. - * @deprecated For internal testing only. Do not use. - */ - expectedLabels?: string[][]; - - /** - * For internal testing only. Do not use. - * @deprecated For internal testing only. Do not use. - */ - explanation?: string; - - /** - * For internal testing only. Do not use. - * @deprecated For internal testing only. Do not use. - */ - start?: StartLabel; -}; - -/** - * Represents a graph. - */ -export type GraphDescriptor = GraphInlineMetadata & { - /** - * Metadata associated with the graph. - */ - metadata?: GraphMetadata; - /** - * The collection of all edges in the graph. - */ - edges: Edge[]; - - /** - * The collection of all nodes in the graph. - */ - nodes: NodeDescriptor[]; - - /** - * All the kits (collections of node handlers) that are used by the graph. - */ - kits?: KitDescriptor[]; - - /** - * Sub-graphs that are also described by this graph representation. - */ - graphs?: SubGraphs; - - /** - * Arguments that are passed to the graph, useful to bind values to graphs. - */ - args?: InputValues; -} & TestProperties; - -/** - * Values that are supplied as inputs to the `NodeHandler`. - */ -export type InputValues = Record; - -/** - * Values that the `NodeHandler` outputs. - */ -export type OutputValues = Partial>; - -/** - * Values that are supplied as part of the graph. These values are merged with - * the `InputValues` and supplied as inputs to the `NodeHandler`. - */ -export type NodeConfiguration = Record; diff --git a/packages/schema/src/scripts/data/board.json b/packages/schema/src/scripts/data/board.json deleted file mode 100644 index 394b8613603..00000000000 --- a/packages/schema/src/scripts/data/board.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "../../../breadboard.schema.json", - "edges": [ - { - "from": "input-1", - "out": "*", - "to": "output-2" - } - ], - "kits": [], - "nodes": [ - { - "id": "input-1", - "type": "input" - }, - { - "id": "output-2", - "type": "output" - } - ] -} diff --git a/packages/schema/src/scripts/generate-json-schema.ts b/packages/schema/src/scripts/generate-json-schema.ts deleted file mode 100755 index fa04870b6c7..00000000000 --- a/packages/schema/src/scripts/generate-json-schema.ts +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as fs from "fs"; -import * as path from "path"; -import { dirname } from "path"; -import { createGenerator, type Config } from "ts-json-schema-generator"; -import { fileURLToPath } from "url"; -import { generateSchemaId } from "./generate-schema-id.js"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -const filePath = path.resolve(__dirname, "../../src/graph.ts"); -if (!fs.existsSync(filePath)) { - throw new Error(`File not found: ${filePath}`); -} - -const tsconfigPath = path.resolve("tsconfig.json"); -if (!fs.existsSync(tsconfigPath)) { - throw new Error(`File not found: ${tsconfigPath}`); -} - -const config: Config = { - additionalProperties: false, - expose: "export", - path: filePath, - schemaId: generateSchemaId(), - sortProps: true, - topRef: true, - tsconfig: tsconfigPath, - type: "GraphDescriptor", -}; - -const outputPath = path.resolve("breadboard.schema.json"); - -const schema = createGenerator(config).createSchema(config.type); - -const schemaString = JSON.stringify(schema, null, "\t"); -fs.writeFileSync(outputPath, schemaString); diff --git a/packages/schema/src/scripts/generate-schema-id.ts b/packages/schema/src/scripts/generate-schema-id.ts deleted file mode 100644 index c877eaab0c1..00000000000 --- a/packages/schema/src/scripts/generate-schema-id.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as path from "path"; -import packageJson from "../../package.json" with { type: "json" }; -import { ascendToPackageDir } from "./util/ascend-to-package-dir.js"; - -export function generateSchemaId() { - const PACKAGE_ROOT = ascendToPackageDir(packageJson.name); - const SCHEMA_PATH = path.relative(PACKAGE_ROOT, "breadboard.schema.json"); - - const GITHUB_OWNER = "breadboard-ai"; - const GITHUB_REPO = "breadboard"; - const GITHUB_REF = `@google-labs/breadboard-schema@${packageJson.version}`; - - const PACKAGE_PATH = "packages/schema"; - - const id = `https://raw.githubusercontent.com/${GITHUB_OWNER}/${GITHUB_REPO}/${GITHUB_REF}/${PACKAGE_PATH}/${SCHEMA_PATH}`; - return id; -} diff --git a/packages/schema/src/scripts/util/ascend-to-package-dir.ts b/packages/schema/src/scripts/util/ascend-to-package-dir.ts deleted file mode 100644 index 3fa5a490bff..00000000000 --- a/packages/schema/src/scripts/util/ascend-to-package-dir.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as fs from "fs"; -import * as path from "path"; - -export function ascendToPackageDir(packageName: string = "breadboard-ai") { - let directory = process.cwd(); - while (directory !== "/") { - const packageJsonPath = path.join(directory, "package.json"); - if (fs.existsSync(packageJsonPath)) { - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")); - if (packageJson.name === packageName) { - return directory; - } - } - directory = path.dirname(directory); - } - throw new Error("Could not find breadboard-ai directory."); -} diff --git a/packages/schema/src/subschema.ts b/packages/schema/src/subschema.ts deleted file mode 100644 index e96ec7b3ee2..00000000000 --- a/packages/schema/src/subschema.ts +++ /dev/null @@ -1,656 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import type { JSONSchema4, JSONSchema4TypeName } from "json-schema"; - -export type JsonSubSchemaAnalysis = - | { isSubSchema: true; details?: never } - | { isSubSchema: false; details: JsonSubSchemaAnalysisDetail[] }; - -export interface JsonSubSchemaAnalysisDetail { - pathA: Array; - pathB: Array; -} - -interface Context { - pathA: Array; - pathB: Array; - details: JsonSubSchemaAnalysisDetail[]; -} - -const PASS_AND_SKIP_REMAINING_CHECKS = Symbol(); -const FAIL_AND_SKIP_REMAINING_CHECKS = Symbol(); - -type Checker = ( - a: JSONSchema4, - b: JSONSchema4, - context: Context -) => - | boolean - | typeof PASS_AND_SKIP_REMAINING_CHECKS - | typeof FAIL_AND_SKIP_REMAINING_CHECKS; - -const CHECKERS: Checker[] = [ - // IMPORTANT: anyOf must come first because it can skip the other checks. - checkAnyOf, - checkType, - checkEnum, - - // string - checkStringLength, - checkStringPattern, - checkStringFormat, - - // number - checkNumberRange, - - // array - checkArrayItems, - - // object - checkObjectProperties, - checkObjectAdditionalProperties, - checkObjectRequiredProperties, -]; - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/type} - */ -const ALL_TYPES = new Set([ - "string", - "number", - "integer", - "object", - "array", - "boolean", - "null", -]); - -const ALL_TYPES_SCHEMA = { type: [...ALL_TYPES] }; - -/** - * Given the JSON Schemas `a` and `b`, determine whether `a` is a sub-schema of - * `b`, and if not explain why. - * - * We say that `a` is a sub-schema of `b` if every JSON Schema constraint in `b` - * is also present in `a` at an equal or higher strictness. Examples: - * - * - If `b` enforces type `string OR number`, then `a` must enforce either - * `string`, `number`, or `string OR number`. - * - If `b` enforces `maxLength` 4, then `a` must enforce `maxLength <= 4` . - * - * Note that the following JSON Schema features are NOT yet implemented by this - * function: - * - * - ~~$ref~~ - * - ~~allOf / oneOf / not~~ - * - ~~const~~ - * - ~~contains~~ - * - ~~contentEncoding / contentMediaType~~ - * - ~~dependentRequired / dependentSchemas / dependencies~~ - * - ~~exclusiveMinimum / exclusiveMaximum~~ - * - ~~if / then / else~~ - * - ~~minContains / maxContains~~ - * - ~~minItems / maxItems~~ - * - ~~minProperties / maxProperties~~ - * - ~~multipleOf~~ - * - ~~prefixItems / uniqueItems / unevaluatedItems~~ - * - ~~propertyNames / patternProperties / unevaluatedProperties~~ - * - ~~tuple~~ - * - * @param a The JSON Schema that is potentially a subset of `b`. - * @param b The JSON Schema that is potentially a superset of `a`. - * - * @returns A {@link JsonSubSchemaAnalysis} object. Use the - * {@link JsonSubSchemaAnalysis.isSubSchema} property to check whether `a` is a - * subschema of `b`. When {@link JsonSubSchemaAnalysis.isSubSchema} is `false`, - * use the {@link JsonSubSchemaAnalysis.details} property to get a detailed - * explanation of why `a` is not a subschema of `b`. - */ -export function analyzeIsJsonSubSchema( - // TODO(aomarks) Should we be using something newer like JSONSchema7? Maybe we - // accept multiple versions? - a: JSONSchema4, - b: JSONSchema4, - context: Context = { pathA: [], pathB: [], details: [] } -): JsonSubSchemaAnalysis { - let anyChecksFailed = false; - for (const checker of CHECKERS) { - const result = checker(a, b, context); - if (result === true) { - // N/A - } else if (result === false) { - anyChecksFailed = true; - // Continue because we want to accumulate multiple errors. - } else if (result === PASS_AND_SKIP_REMAINING_CHECKS) { - break; - } else if (result === FAIL_AND_SKIP_REMAINING_CHECKS) { - anyChecksFailed = true; - break; - } else { - result satisfies never; - } - } - if (anyChecksFailed) { - return { isSubSchema: false, details: context.details }; - } - return { isSubSchema: true }; -} - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/type} - */ -function checkType(a: JSONSchema4, b: JSONSchema4, context: Context): boolean { - if (a.type === b.type) { - // Fast path to avoid Set allocations for very common simple case of e.g. - // `{type: "string"} vs `{type: "number"}. - return true; - } - const aTypes = normalizedTypes(a); - const bTypes = normalizedTypes(b); - if (aTypes.has("integer") && bTypes.has("number")) { - // All integers are numbers, but not all numbers are integers. So, here is - // special handling to allow the case where A is an integer and B is a - // number (but not vice-versa). - aTypes.delete("integer"); - aTypes.add("number"); - } - if (!isSubsetOf(aTypes, bTypes)) { - context.details.push({ - pathA: [...context.pathA, "type"], - pathB: [...context.pathB, "type"], - }); - return false; - } - return true; -} - -function normalizedTypes(schema: JSONSchema4): Set { - if (schema.type === undefined) { - // No type means all types. - return ALL_TYPES; - } - return coerceSet(schema.type); -} - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/enum} - */ -function checkEnum(a: JSONSchema4, b: JSONSchema4, context: Context): boolean { - if (b.enum === undefined) { - return true; - } - if ( - a.enum === undefined || - (a.enum.length === 0 && b.enum.length > 0) || - !isSubsetOf(coerceSet(a.enum), coerceSet(b.enum)) - ) { - context.details.push({ - pathA: [...context.pathA, "enum"], - pathB: [...context.pathB, "enum"], - }); - return false; - } - return true; -} - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/string#length} - */ -function checkStringLength( - a: JSONSchema4, - b: JSONSchema4, - context: Context -): boolean { - if (b.minLength === undefined && b.maxLength === undefined) { - return true; - } - - let ok = true; - - const aMin = a.minLength ?? 0; - const bMin = b.minLength ?? 0; - if (aMin < bMin) { - ok = false; - context.details.push({ - pathA: [...context.pathA, "minLength"], - pathB: [...context.pathB, "minLength"], - }); - } - - const aMax = a.maxLength ?? Number.MAX_VALUE; - const bMax = b.maxLength ?? Number.MAX_VALUE; - if (aMax > bMax) { - ok = false; - context.details.push({ - pathA: [...context.pathA, "maxLength"], - pathB: [...context.pathB, "maxLength"], - }); - } - - return ok; -} - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/string#regexp} - */ -function checkStringPattern( - a: JSONSchema4, - b: JSONSchema4, - context: Context -): boolean { - if (b.pattern === undefined) { - return true; - } - if (a.pattern !== b.pattern) { - context.details.push({ - pathA: [...context.pathA, "pattern"], - pathB: [...context.pathB, "pattern"], - }); - return false; - } - return true; -} - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/string#format} - */ -function checkStringFormat( - a: JSONSchema4, - b: JSONSchema4, - context: Context -): boolean { - if (b.format === undefined) { - return true; - } - if (a.format !== b.format) { - context.details.push({ - pathA: [...context.pathA, "format"], - pathB: [...context.pathB, "format"], - }); - return false; - } - return true; -} - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/numeric#range} - */ -function checkNumberRange( - a: JSONSchema4, - b: JSONSchema4, - context: Context -): boolean { - if (b.minimum === undefined && b.maximum === undefined) { - return true; - } - - const aMin = a.minimum ?? 0; - const bMin = b.minimum ?? 0; - if (aMin < bMin) { - context.details.push({ - pathA: [...context.pathA, "minimum"], - pathB: [...context.pathB, "minimum"], - }); - return false; - } - const aMax = a.maximum ?? Number.MAX_VALUE; - const bMax = b.maximum ?? Number.MAX_VALUE; - if (aMax > bMax) { - context.details.push({ - pathA: [...context.pathA, "maximum"], - pathB: [...context.pathB, "maximum"], - }); - return false; - } - return true; -} - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/array#items} - */ -function checkArrayItems( - a: JSONSchema4, - b: JSONSchema4, - context: Context -): boolean { - if (b.items === undefined) { - return true; - } - if (Array.isArray(a.items) || Array.isArray(b.items)) { - // TODO(aomarks) Implement tuple support. - return true; - } - // TODO(aomarks) Recurse in a way that won't lose context (once context is - // actually used for anything). - context.pathA.push("items"); - context.pathB.push("items"); - const ok = analyzeIsJsonSubSchema( - a.items ?? ALL_TYPES_SCHEMA, - b.items, - context - ).isSubSchema; - context.pathA.pop(); - context.pathB.pop(); - return ok; -} - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/object#properties} - */ -function checkObjectProperties( - a: JSONSchema4, - b: JSONSchema4, - context: Context -): boolean { - if (a.properties === undefined) { - return true; - } - for (const [name, aSchema] of Object.entries(a.properties)) { - const bSchema = b.properties?.[name]; - if (bSchema !== undefined) { - // B also specifies this property, check compatibility. - context.pathA.push("properties", name); - context.pathB.push("properties", name); - const { isSubSchema } = analyzeIsJsonSubSchema(aSchema, bSchema, context); - context.pathA.pop(); - context.pathB.pop(); - if (!isSubSchema) { - return false; - } - } else if ( - b.additionalProperties === true || - b.additionalProperties === /* defaults to true */ undefined - ) { - // B allows any additional property. - continue; - } else if (b.additionalProperties === false) { - // B doesn't allow any additional properties. - context.details.push({ - pathA: [...context.pathA, "properties", name], - pathB: [...context.pathB, "additionalProperties"], - }); - return false; - } else { - // B allows additional properties but constrains their schema. - context.pathA.push("properties", name); - context.pathB.push("additionalProperties"); - const { isSubSchema } = analyzeIsJsonSubSchema( - aSchema, - b.additionalProperties, - context - ); - context.pathA.pop(); - context.pathB.pop(); - if (!isSubSchema) { - return false; - } - } - } - return true; -} - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/object#additionalproperties} - */ -function checkObjectAdditionalProperties( - a: JSONSchema4, - b: JSONSchema4, - context: Context -): boolean { - // The additionalProperties constraint can be true (any additional property is - // OK), false (no additional properties are OK), or an object (additional - // property is OK as long as it matches that type). - const bAdditional = b.additionalProperties ?? true; - if (bAdditional === true) { - // A | B | Result | - // ----- | ------| ------- | - // true | true | true | T - // false | true | true | T - // {...} | true | true | T - return true; - } - const aAdditional = a.additionalProperties ?? true; - if (aAdditional === false) { - // A | B | Result | - // ----- | ------| ------- | - // false | false | true | T - // false | {...} | true | T - return true; - } - if (bAdditional === false) { - // A | B | Result | - // ----- | ------| ------- | - // {...} | false | false | T - // true | false | false | T - context.details.push({ - pathA: [...context.pathA, "additionalProperties"], - pathB: [...context.pathB, "additionalProperties"], - }); - return false; - } - // A | B | Result | - // ----- | ------| ------- | - // true | {...} | compare | T - // {...} | {...} | compare | - context.pathA.push("additionalProperties"); - context.pathB.push("additionalProperties"); - const result = analyzeIsJsonSubSchema( - aAdditional === true ? {} : aAdditional, - bAdditional, - context - ).isSubSchema; - context.pathA.pop(); - context.pathB.pop(); - return result; -} - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/object#required} - */ -function checkObjectRequiredProperties( - a: JSONSchema4, - b: JSONSchema4, - context: Context -): boolean { - if (typeof a.required === "boolean" || typeof b.required === "boolean") { - // TODO(aomarks) Validate that required can't actually be a boolean. The - // `json-schema` types package say that it can be, but the docs don't - // mention this, so it doesn't seem right. - return true; - } - if (b.required === undefined || b.required.length === 0) { - return true; - } - const aRequired = new Set(a.required ?? []); - let ok = true; - for (let i = 0; i < b.required.length; i++) { - const name = b.required[i]; - if (!aRequired.has(name)) { - ok = false; - context.details.push({ - pathA: [...context.pathA, "required"], - pathB: [...context.pathB, "required", i], - }); - } - } - return ok; -} - -/** - * {@link https://json-schema.org/understanding-json-schema/reference/combining#anyOf} - */ -function checkAnyOf( - a: JSONSchema4, - b: JSONSchema4, - context: Context -): - | boolean - | typeof PASS_AND_SKIP_REMAINING_CHECKS - | typeof FAIL_AND_SKIP_REMAINING_CHECKS { - if (a.anyOf !== undefined) { - // ALL possibilities from A must satisfy B. - for (let idxA = 0; idxA < a.anyOf.length; idxA++) { - const originalSubA = a.anyOf[idxA]; - const modifiedSubA = inheritParentConstraintsIntoAnyOfEntry( - a, - originalSubA - ); - if (b.anyOf === undefined) { - // B is NOT an `anyOf`, so check each A directly against B. - // - // We need to be a bit clever here, because we ARE passing down the - // context, but we're doing so with "fake" paths (see - // `inheritParentConstraintsIntoAnyOfEntry`). So we do this: - // - // 1. Make a temporary context so that we can easily isolate the details - // from this recursion from any other details we might already have. - // 2. Undo the effect of `inheritParentConstraintsIntoAnyOfEntry` using - // `repairDetailPathsForInheritedProperties`. - // 3. Merge back in the details we temporarily excluded in (1). - const tempDetails: JsonSubSchemaAnalysisDetail[] = []; - const tempContext = { ...context, details: tempDetails }; - context.pathA.push("anyOf", idxA); - const ok = analyzeIsJsonSubSchema( - modifiedSubA, - b, - tempContext - ).isSubSchema; - context.pathA.pop(); - context.pathA.pop(); - if (!ok) { - context.details.push( - ...repairDetailPathsForInheritedProperties( - tempDetails, - idxA, - originalSubA - ) - ); - return FAIL_AND_SKIP_REMAINING_CHECKS; - } - } else { - // B is also an `anyOf`, so check that ALL possibilities from A - // satisfies AT LEAST ONE posibility from B. - // - // PERFORMANCE WARNING: O(n^2) comparisons! - let found = false; - for (const subB of b.anyOf) { - if ( - analyzeIsJsonSubSchema( - modifiedSubA, - inheritParentConstraintsIntoAnyOfEntry(b, subB) - // Note we do NOT pass down context here because we don't want to - // accumulate details, because we're _searching_ for a match, not - // asserting a match. - ).isSubSchema - ) { - found = true; - break; - } - } - if (!found) { - context.details.push({ - pathA: [...context.pathA, "anyOf", idxA], - pathB: [...context.pathB, "anyOf"], - }); - return FAIL_AND_SKIP_REMAINING_CHECKS; - } - } - } - return PASS_AND_SKIP_REMAINING_CHECKS; - } else if (b.anyOf !== undefined) { - // Only B is an `anyOf`. Ensure that A satisfies AT LEAST ONE possibility - // from B. - for (const subB of b.anyOf) { - if ( - analyzeIsJsonSubSchema( - a, - inheritParentConstraintsIntoAnyOfEntry(b, subB) - // Note we do NOT pass down context here because we don't want to - // accumulate details, because we're _searching_ for a match, not - // asserting a match. - ).isSubSchema - ) { - return PASS_AND_SKIP_REMAINING_CHECKS; - } - } - context.details.push({ - pathA: [...context.pathA], - pathB: [...context.pathB, "anyOf"], - }); - return FAIL_AND_SKIP_REMAINING_CHECKS; - } else { - return true; - } -} - -/** - * If you have e.g. `{ maxLength: 4, anyOf: { A, B } }` then the `maxLength` - * constraint implicitly applies to both `A` and `B`. This function copies any - * such constraints from a parent JSON schema object into one of its given - * `anyOf` entries so that it can more easily be analyzed. - * - * See - * {@link https://json-schema.org/understanding-json-schema/reference/combining#factoringschemas}. - */ -function inheritParentConstraintsIntoAnyOfEntry( - parentSchema: JSONSchema4, - anyOfEntry: JSONSchema4 -): JSONSchema4 { - if (Object.keys(parentSchema).length === 1) { - // We assume `parent` has `anyOf`, so if there's only 1 property then it - // must be `anyOf`, which we can ignore and save a copy. - return anyOfEntry; - } - return { ...parentSchema, anyOf: undefined, ...anyOfEntry }; -} - -function repairDetailPathsForInheritedProperties( - details: JsonSubSchemaAnalysisDetail[], - idxA: number, - anyOfEntry: JSONSchema4 -): JsonSubSchemaAnalysisDetail[] { - return details.map((detail) => { - const { pathA, pathB } = detail; - // If we see a path that's within the anyOf entry, but it's a property that - // doesn't exist on the original anyOf entry, then it must have been - // inherited, so we should trim off the first 2 path components because - // really they came from the parent. - if ( - pathA[0] === "anyOf" && - pathA[1] === idxA && - anyOfEntry[pathA[2]] === undefined - ) { - return { - pathA: pathA.slice(2), - pathB, - }; - } else { - return detail; - } - }); -} - -function coerceSet(value: T | T[] | undefined): Set { - return new Set( - value === undefined ? [] : Array.isArray(value) ? value : [value] - ); -} - -// Replace with -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/isSubsetOf -// when Node 22 is our minimum version. -function isSubsetOf(a: Set, b: Set): boolean { - if (a.size > b.size) { - return false; - } - for (const item of a) { - if (!b.has(item)) { - return false; - } - } - return true; -} diff --git a/packages/schema/src/tests/main.test.ts b/packages/schema/src/tests/main.test.ts deleted file mode 100644 index b9555ea5492..00000000000 --- a/packages/schema/src/tests/main.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import Ajv, { type ValidateFunction } from "ajv"; -import * as fs from "fs"; -import * as assert from "node:assert"; -import test from "node:test"; -import * as path from "path"; -import { ascendToPackageDir } from "../scripts/util/ascend-to-package-dir.js"; -import { getBoardFiles } from "./util/get-board-files.js"; - -const ajv = new Ajv(); -let validate: ValidateFunction; - -import schema from "../../breadboard.schema.json" with { type: "json" }; - -test.before(() => { - validate = ajv.compile(schema); -}); - -test("Schema is valid.", async () => { - assert.ok(validate); -}); - -const packageRoot = ascendToPackageDir(); -const allBoardFiles = getBoardFiles(packageRoot); - -for (const file of allBoardFiles) { - const relativePath = path.relative(packageRoot, file); - test(`Validating ${relativePath}`, async () => { - const data = JSON.parse(fs.readFileSync(file, "utf-8")); - const valid = validate(data); - if (!valid) { - console.error(validate.errors); - } - assert.ok(valid); - }); -} diff --git a/packages/schema/src/tests/subschema.test.ts b/packages/schema/src/tests/subschema.test.ts deleted file mode 100644 index 599b50a60b6..00000000000 --- a/packages/schema/src/tests/subschema.test.ts +++ /dev/null @@ -1,998 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { type JSONSchema4 } from "json-schema"; -import * as assert from "node:assert/strict"; -import { describe, test } from "node:test"; -import { - analyzeIsJsonSubSchema, - type JsonSubSchemaAnalysisDetail, -} from "../subschema.js"; - -function ok(testName: string, a: JSONSchema4, b: JSONSchema4) { - test(testName, () => { - assert.equal(analyzeIsJsonSubSchema(a, b).isSubSchema, true); - }); -} - -function notOk(testName: string, a: JSONSchema4, b: JSONSchema4) { - test(testName, () => { - assert.equal(analyzeIsJsonSubSchema(a, b).isSubSchema, false); - }); -} - -function detail( - testName: string, - a: JSONSchema4, - b: JSONSchema4, - expectedDetails: JsonSubSchemaAnalysisDetail[] | undefined -) { - test(testName, () => { - assert.deepEqual(analyzeIsJsonSubSchema(a, b).details, expectedDetails); - }); -} - -const EXHAUSTIVE_SCHEMA: JSONSchema4 = { - type: ["string", "number", "integer", "object", "array", "boolean", "null"], -}; - -describe("type", () => { - ok("string vs string", { type: "string" }, { type: "string" }); - ok("string vs [string]", { type: "string" }, { type: ["string"] }); - ok( - "string vs [number, string]", - { type: "string" }, - { type: ["number", "string"] } - ); - ok("string vs missing", { type: "string" }, {}); - ok("missing vs missing", {}, {}); - ok("exhaustive vs exhaustive", EXHAUSTIVE_SCHEMA, EXHAUSTIVE_SCHEMA); - ok("exhaustive vs missing", EXHAUSTIVE_SCHEMA, {}); - ok( - "missing vs exhaustive", - {}, - { - type: [ - "string", - "number", - "integer", - "object", - "array", - "boolean", - "null", - ], - } - ); - - notOk("string vs number", { type: "string" }, { type: "number" }); - notOk("number vs string", { type: "number" }, { type: "string" }); - notOk("string vs [number]", { type: "string" }, { type: ["number"] }); - notOk("[string] vs number", { type: ["string"] }, { type: "number" }); - notOk( - "[number, string] vs string", - { type: ["number", "string"] }, - { type: "string" } - ); - notOk("missing vs string", {}, { type: "string" }); - notOk("object vs array", { type: "object" }, { type: "array" }); - - // Note type=number vs type=integer is an interesting case, but that's tested - // in the "number" suite later. -}); - -describe("string", () => { - describe("length", () => { - ok( - "equal", - { type: "string", minLength: 3, maxLength: 6 }, - { type: "string", minLength: 3, maxLength: 6 } - ); - ok( - "inside left", - { type: "string", minLength: 4, maxLength: 6 }, - { type: "string", minLength: 3, maxLength: 6 } - ); - ok( - "inside right", - { type: "string", minLength: 3, maxLength: 5 }, - { type: "string", minLength: 3, maxLength: 6 } - ); - ok( - "inside both", - { type: "string", minLength: 4, maxLength: 5 }, - { type: "string", minLength: 3, maxLength: 6 } - ); - - notOk( - "outside left", - { type: "string", minLength: 2, maxLength: 6 }, - { type: "string", minLength: 3, maxLength: 6 } - ); - notOk( - "outside right", - { type: "string", minLength: 3, maxLength: 7 }, - { type: "string", minLength: 3, maxLength: 6 } - ); - notOk( - "outside both", - { type: "string", minLength: 2, maxLength: 7 }, - { type: "string", minLength: 3, maxLength: 6 } - ); - - ok("both missing", { type: "string" }, { type: "string" }); - ok( - "b missing", - { type: "string", minLength: 2, maxLength: 7 }, - { type: "string" } - ); - notOk( - "a missing", - { type: "string" }, - { type: "string", minLength: 2, maxLength: 7 } - ); - }); - - describe("pattern", () => { - ok( - "equal", - { type: "string", pattern: "[0-9]+" }, - { type: "string", pattern: "[0-9]+" } - ); - notOk( - "not equal", - { type: "string", pattern: "[0-9]+" }, - { type: "string", pattern: "[a-z]+" } - ); - - ok("both missing", { type: "string" }, { type: "string" }); - ok("b missing", { type: "string", pattern: "[0-9]+" }, { type: "string" }); - notOk( - "a missing", - { type: "string" }, - { type: "string", pattern: "[a-z]+" } - ); - }); - - describe("format", () => { - ok( - "equal", - { type: "string", format: "uri" }, - { type: "string", format: "uri" } - ); - notOk( - "not equal", - { type: "string", format: "uri" }, - { type: "string", format: "email" } - ); - - ok("both missing", { type: "string" }, { type: "string" }); - ok("b missing", { type: "string", format: "uri" }, { type: "string" }); - notOk("a missing", { type: "string" }, { type: "string", format: "email" }); - }); -}); - -describe("number", () => { - describe("number/integer", () => { - ok("number vs number", { type: "number" }, { type: "number" }); - ok("integer vs number", { type: "integer" }, { type: "number" }); - notOk("number vs integer", { type: "number" }, { type: "integer" }); - }); - - describe("inclusive range", () => { - ok( - "equal", - { type: "number", minimum: 3, maximum: 6 }, - { type: "number", minimum: 3, maximum: 6 } - ); - ok( - "inside left", - { type: "number", minimum: 4, maximum: 6 }, - { type: "number", minimum: 3, maximum: 6 } - ); - ok( - "inside right", - { type: "number", minimum: 3, maximum: 5 }, - { type: "number", minimum: 3, maximum: 6 } - ); - ok( - "inside both", - { type: "number", minimum: 4, maximum: 5 }, - { type: "number", minimum: 3, maximum: 6 } - ); - notOk( - "outside left", - { type: "number", minimum: 2, maximum: 6 }, - { type: "number", minimum: 3, maximum: 6 } - ); - notOk( - "outside right", - { type: "number", minimum: 3, maximum: 7 }, - { type: "number", minimum: 3, maximum: 6 } - ); - notOk( - "outside both", - { type: "number", minimum: 2, maximum: 7 }, - { type: "number", minimum: 3, maximum: 6 } - ); - ok("both missing", { type: "number" }, { type: "number" }); - ok( - "b missing", - { type: "number", minimum: 2, maximum: 7 }, - { type: "number" } - ); - notOk( - "a missing", - { type: "number" }, - { type: "number", minimum: 2, maximum: 7 } - ); - }); - - describe("exclusive range", () => { - // TODO(aomarks) Implement this. - }); - - describe("multipleOf", () => { - // TODO(aomarks) Implement this. - }); -}); - -describe("array", () => { - describe("items.type", () => { - ok( - "string vs string", - { type: "array", items: { type: "string" } }, - { type: "array", items: { type: "string" } } - ); - notOk( - "string vs number", - { type: "array", items: { type: "string" } }, - { type: "array", items: { type: "number" } } - ); - notOk( - "number vs string", - { type: "array", items: { type: "number" } }, - { type: "array", items: { type: "string" } } - ); - - ok( - "string[] vs string[]", - { type: "array", items: { type: "array", items: { type: "string" } } }, - { type: "array", items: { type: "array", items: { type: "string" } } } - ); - ok( - "string[][] vs string[][]", - { - type: "array", - items: { - type: "array", - items: { type: "array", items: { type: "string" } }, - }, - }, - { - type: "array", - items: { - type: "array", - items: { type: "array", items: { type: "string" } }, - }, - } - ); - notOk( - "string[] vs number[]", - { type: "array", items: { type: "array", items: { type: "string" } } }, - { type: "array", items: { type: "array", items: { type: "number" } } } - ); - notOk( - "number[] vs string[]", - { type: "array", items: { type: "array", items: { type: "number" } } }, - { type: "array", items: { type: "array", items: { type: "string" } } } - ); - notOk( - "string[] vs string[][]", - { type: "array", items: { type: "array", items: { type: "string" } } }, - { - type: "array", - items: { - type: "array", - items: { type: "array", items: { type: "string" } }, - }, - } - ); - notOk( - "string[4] vs string[3]", - { - type: "array", - items: { type: "array", items: { type: "string", maxLength: 4 } }, - }, - { - type: "array", - items: { type: "array", items: { type: "string", maxLength: 3 } }, - } - ); - - ok("missing vs missing", { type: "array" }, { type: "array" }); - ok( - "string vs missing", - { type: "array", items: { type: "string" } }, - { type: "array" } - ); - - ok( - "string vs any", - { type: "array", items: { type: "string" } }, - { - type: "array", - items: { - type: [ - "string", - "number", - "integer", - "object", - "array", - "boolean", - "null", - ], - }, - } - ); - ok( - "missing vs exhaustive", - { type: "array" }, - { - type: "array", - items: EXHAUSTIVE_SCHEMA, - } - ); - ok( - "exhaustive vs missing", - { - type: "array", - items: EXHAUSTIVE_SCHEMA, - }, - { type: "array" } - ); - notOk( - "missing vs string", - { type: "array" }, - { type: "array", items: { type: "number" } } - ); - }); -}); - -describe("object", () => { - describe("properties", () => { - ok( - "string vs string", - { type: "object", properties: { foo: { type: "string" } } }, - { type: "object", properties: { foo: { type: "string" } } } - ); - notOk( - "string vs number", - { type: "object", properties: { foo: { type: "string" } } }, - { type: "object", properties: { foo: { type: "number" } } } - ); - notOk( - "number vs string", - { type: "object", properties: { foo: { type: "number" } } }, - { type: "object", properties: { foo: { type: "string" } } } - ); - - ok( - "string<3> vs string<4>", - { type: "object", properties: { foo: { type: "string", maxLength: 3 } } }, - { type: "object", properties: { foo: { type: "string", maxLength: 4 } } } - ); - notOk( - "string<4> vs string<3>", - { type: "object", properties: { foo: { type: "string", maxLength: 4 } } }, - { type: "object", properties: { foo: { type: "string", maxLength: 3 } } } - ); - - ok( - "string vs missing", - { type: "object", properties: { foo: { type: "string" } } }, - { type: "object" } - ); - ok( - "missing vs string", - { type: "object" }, - { type: "object", properties: { foo: { type: "string" } } } - ); - }); - - describe("additionalProperties", () => { - describe("without properties", () => { - ok( - "true vs true", - { type: "object", additionalProperties: true }, - { type: "object", additionalProperties: true } - ); - ok( - "false vs true", - { type: "object", additionalProperties: false }, - { type: "object", additionalProperties: true } - ); - ok( - "{str} vs true", - { type: "object", additionalProperties: { type: "string" } }, - { type: "object", additionalProperties: true } - ); - ok( - "false vs false", - { type: "object", additionalProperties: false }, - { type: "object", additionalProperties: false } - ); - ok( - "false vs {str}", - { type: "object", additionalProperties: false }, - { type: "object", additionalProperties: { type: "string" } } - ); - ok( - "false vs {}", - { type: "object", additionalProperties: false }, - { type: "object", additionalProperties: {} } - ); - notOk( - "{str} vs false", - { type: "object", additionalProperties: { type: "string" } }, - { type: "object", additionalProperties: false } - ); - notOk( - "true vs false", - { type: "object", additionalProperties: true }, - { type: "object", additionalProperties: false } - ); - ok( - "true vs {}", - { type: "object", additionalProperties: true }, - { type: "object", additionalProperties: {} } - ); - notOk( - "true vs {str}", - { type: "object", additionalProperties: true }, - { type: "object", additionalProperties: { type: "string" } } - ); - ok( - "{} vs {}", - { type: "object", additionalProperties: {} }, - { type: "object", additionalProperties: {} } - ); - ok( - "{str} vs {str}", - { type: "object", additionalProperties: { type: "string" } }, - { type: "object", additionalProperties: { type: "string" } } - ); - ok( - "{str} vs {}", - { type: "object", additionalProperties: { type: "string" } }, - { type: "object", additionalProperties: {} } - ); - notOk( - "{} vs {str}", - { type: "object", additionalProperties: {} }, - { type: "object", additionalProperties: { type: "string" } } - ); - }); - - describe("with properties", () => {}); - notOk( - "a:false/p:{foo} vs a:false/p:-", - { - type: "object", - additionalProperties: false, - properties: { foo: { type: "string" } }, - }, - { - type: "object", - additionalProperties: false, - } - ); - ok( - "{} vs {foo}", - { - type: "object", - additionalProperties: false, - }, - { - type: "object", - additionalProperties: false, - properties: { foo: { type: "string" } }, - } - ); - ok( - "{foo} vs {foo}", - { - type: "object", - additionalProperties: false, - properties: { foo: { type: "string" } }, - }, - { - type: "object", - additionalProperties: false, - properties: { foo: { type: "string" } }, - } - ); - notOk( - "{foo} vs {bar}", - { - type: "object", - additionalProperties: false, - properties: { foo: { type: "string" } }, - }, - { - type: "object", - additionalProperties: false, - properties: { bar: { type: "string" } }, - } - ); - notOk( - "{foo,bar} vs {foo}", - { - type: "object", - additionalProperties: false, - properties: { - foo: { type: "string" }, - bar: { type: "string" }, - }, - }, - { - type: "object", - additionalProperties: false, - properties: { foo: { type: "string" } }, - } - ); - ok( - "{foo} vs {foo,bar}", - { - type: "object", - additionalProperties: false, - properties: { - foo: { type: "string" }, - }, - }, - { - type: "object", - additionalProperties: false, - properties: { - foo: { type: "string" }, - bar: { type: "string" }, - }, - } - ); - }); - - describe("requiredProperties", () => { - ok( - "{} vs {}", - { type: "object", required: [] }, - { type: "object", required: [] } - ); - ok( - "{foo} vs {foo}", - { type: "object", required: ["foo"] }, - { type: "object", required: ["foo"] } - ); - ok( - "{foo} vs {}", - { type: "object", required: ["foo"] }, - { type: "object", required: [] } - ); - ok( - "{foo,bar} vs {foo}", - { type: "object", required: ["foo", "bar"] }, - { type: "object", required: ["bar"] } - ); - notOk( - "{} vs {foo}", - { type: "object", required: [] }, - { type: "object", required: ["foo"] } - ); - notOk( - "{foo} vs {bar}", - { type: "object", required: ["foo"] }, - { type: "object", required: ["bar"] } - ); - notOk( - "{foo} vs {foo,bar}", - { type: "object", required: ["foo"] }, - { type: "object", required: ["foo", "bar"] } - ); - }); -}); - -describe("enum", () => { - ok("[foo] vs [foo]", { enum: ["foo"] }, { enum: ["foo"] }); - ok("[42] vs [42]", { enum: [42] }, { enum: [42] }); - ok("[foo] vs [foo, 42]", { enum: ["foo"] }, { enum: ["foo", 42] }); - ok("[] vs []", { enum: [] }, { enum: [] }); - ok("[foo] vs missing", { enum: ["foo"] }, {}); - - notOk("[foo, 42] vs [42]", { enum: ["foo", 42] }, { enum: [42] }); - notOk("[foo] vs [42]", { enum: ["foo"] }, { enum: [42] }); - notOk("[foo] vs []", { enum: ["foo"] }, { enum: [] }); - notOk("[] vs [foo]", { enum: [] }, { enum: ["foo"] }); - notOk("missing vs [foo]", {}, { enum: ["foo"] }); - notOk("['42'] vs [42]", { enum: ["42"] }, { enum: [42] }); -}); - -describe("anyOf", () => { - describe("with / with", () => { - ok( - "[str, num, bool] vs [str, num, bool]", - { anyOf: [{ type: "string" }, { type: "number" }, { type: "boolean" }] }, - { anyOf: [{ type: "string" }, { type: "number" }, { type: "boolean" }] } - ); - ok( - "[str, num, bool] vs [bool, str, num]", - { anyOf: [{ type: "string" }, { type: "number" }, { type: "boolean" }] }, - { anyOf: [{ type: "boolean" }, { type: "string" }, { type: "number" }] } - ); - ok( - "[str, num] vs [str, num, bool]", - { anyOf: [{ type: "string" }, { type: "number" }] }, - { anyOf: [{ type: "string" }, { type: "number" }, { type: "boolean" }] } - ); - ok( - "[str:email, str:uri]:3 vs [str:email, str:uri]:4", - { - maxLength: 3, - anyOf: [ - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - ], - }, - { - maxLength: 4, - anyOf: [ - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - ], - } - ); - ok( - "[str:email:3, str:uri:3] vs [str:email, str:uri]:4", - { - anyOf: [ - { type: "string", format: "email", maxLength: 3 }, - { type: "string", format: "uri", maxLength: 3 }, - ], - }, - { - maxLength: 4, - anyOf: [ - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - ], - } - ); - ok( - "[] vs [str, num]", - { anyOf: [] }, - { anyOf: [{ type: "string" }, { type: "number" }] } - ); - ok( - "anyOf[str, num] vs type[str, num]", - { - anyOf: [{ type: "string" }, { type: "number" }], - }, - { - type: ["string", "number"], - } - ); - - notOk( - "[str, num, bool] vs [str, num]", - { anyOf: [{ type: "string" }, { type: "number" }, { type: "boolean" }] }, - { anyOf: [{ type: "string" }, { type: "number" }] } - ); - notOk( - "[str:email, str:uri]:4 vs [str:email, str:uri]:3", - { - maxLength: 4, - anyOf: [ - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - ], - }, - { - maxLength: 3, - anyOf: [ - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - ], - } - ); - notOk( - "[str, num] vs []", - { anyOf: [{ type: "string" }, { type: "number" }] }, - { anyOf: [] } - ); - notOk( - "anyOf[str, bool] vs type[str, num]", - { - anyOf: [{ type: "string" }, { type: "boolean" }], - }, - { - type: ["string", "number"], - } - ); - }); - - describe("with / without", () => { - ok( - "[str:email, str:uri] vs str", - { - anyOf: [ - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - ], - }, - { type: "string" } - ); - ok( - "[str, num] vs empty", - { anyOf: [{ type: "string" }, { type: "number" }] }, - {} - ); - ok( - "[str:email, str:uri]:3 vs str:4", - { - maxLength: 3, - anyOf: [ - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - ], - }, - { type: "string", maxLength: 4 } - ); - notOk( - "[str, num] vs bool", - { anyOf: [{ type: "string" }, { type: "number" }] }, - { type: "boolean" } - ); - notOk( - "[str, num] vs str", - { anyOf: [{ type: "string" }, { type: "number" }] }, - { type: "string" } - ); - notOk( - "[str:email, str:uri] vs str:date", - { - anyOf: [ - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - ], - }, - { type: "string", format: "date" } - ); - notOk( - "[str:email, str:uri]:4 vs str:3", - { - maxLength: 4, - anyOf: [ - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - ], - }, - { type: "string", maxLength: 3 } - ); - }); - - describe("without / with", () => { - ok( - "str vs [str, num]", - { type: "string" }, - { anyOf: [{ type: "string" }, { type: "number" }] } - ); - ok( - "anyOf[str, num] vs type[str, num]", - { anyOf: [{ type: "string" }, { type: "number" }] }, - { type: ["string", "number"] } - ); - - notOk( - "bool vs [str, num]", - { type: "boolean" }, - { anyOf: [{ type: "string" }, { type: "number" }] } - ); - notOk( - "str vs [str:email, str:uri]", - { type: "string" }, - { - anyOf: [ - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - ], - } - ); - notOk( - "empty vs [str, num]", - {}, - { anyOf: [{ type: "string" }, { type: "number" }] } - ); - notOk( - "string vs [str]:3", - { type: "string" }, - { - maxLength: 3, - anyOf: [{ type: "string" }], - } - ); - notOk( - "type[str, num] vs anyOf[str, bool]", - { type: ["string", "number"] }, - { anyOf: [{ type: "string" }, { type: "boolean" }] } - ); - }); -}); - -describe("details", () => { - detail("type", { type: "string" }, { type: "number" }, [ - { pathA: ["type"], pathB: ["type"] }, - ]); - - describe("string", () => { - detail( - "pattern", - { type: "string", pattern: "[0-9]+" }, - { type: "string", pattern: "[a-z]+" }, - [{ pathA: ["pattern"], pathB: ["pattern"] }] - ); - detail( - "format", - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - [{ pathA: ["format"], pathB: ["format"] }] - ); - detail( - "length", - { type: "string", minLength: 2, maxLength: 5 }, - { type: "string", minLength: 3, maxLength: 4 }, - [ - { pathA: ["minLength"], pathB: ["minLength"] }, - { pathA: ["maxLength"], pathB: ["maxLength"] }, - ] - ); - }); - - describe("number", () => { - detail( - "minimum", - { type: "number", minimum: 3 }, - { type: "number", minimum: 4 }, - [{ pathA: ["minimum"], pathB: ["minimum"] }] - ); - detail( - "maximum", - { type: "number", maximum: 4 }, - { type: "number", maximum: 3 }, - [{ pathA: ["maximum"], pathB: ["maximum"] }] - ); - }); - - detail("enum", { enum: ["foo"] }, { enum: [42] }, [ - { pathA: ["enum"], pathB: ["enum"] }, - ]); - - describe("array", () => { - detail( - "items.type", - { type: "array", items: { type: "string" } }, - { type: "array", items: { type: "number" } }, - [{ pathA: ["items", "type"], pathB: ["items", "type"] }] - ); - }); - - describe("object", () => { - detail( - "properties", - { type: "object", properties: { foo: { type: "string" } } }, - { type: "object", properties: { foo: { type: "number" } } }, - [ - { - pathA: ["properties", "foo", "type"], - pathB: ["properties", "foo", "type"], - }, - ] - ); - - detail( - "additionalProperties (setting)", - { type: "object" }, - { type: "object", additionalProperties: false }, - [ - { - pathA: ["additionalProperties"], - pathB: ["additionalProperties"], - }, - ] - ); - - detail( - "additionalProperties (extra property)", - { - type: "object", - additionalProperties: false, - properties: { foo: { type: "string" } }, - }, - { - type: "object", - additionalProperties: false, - }, - [ - { - pathA: ["properties", "foo"], - pathB: ["additionalProperties"], - }, - ] - ); - - detail( - "requiredProperties", - { - type: "object", - required: ["foo", "baz"], - }, - { - type: "object", - required: ["foo", "bar", "baz", "qux"], - }, - [ - { - pathA: ["required"], - pathB: ["required", 1], - }, - { - pathA: ["required"], - pathB: ["required", 3], - }, - ] - ); - }); - - describe("anyOf", () => { - detail( - "with/with", - { anyOf: [{ type: "string" }, { type: "boolean" }, { type: "number" }] }, - { anyOf: [{ type: "string" }, { type: "number" }] }, - [{ pathA: ["anyOf", 1], pathB: ["anyOf"] }] - ); - detail( - "with/without", - { anyOf: [{ type: "string" }, { type: "number" }] }, - { type: "string" }, - [{ pathA: ["anyOf", 1, "type"], pathB: ["type"] }] - ); - detail( - "with/without (inherited constraint)", - { - maxLength: 4, - anyOf: [ - { type: "string", format: "email" }, - { type: "string", format: "uri" }, - ], - }, - { type: "string", maxLength: 3 }, - [{ pathA: ["maxLength"], pathB: ["maxLength"] }] - ); - detail( - "with/without (own constraint)", - { - anyOf: [ - { type: "string", format: "email", maxLength: 4 }, - { type: "string", format: "uri", maxLength: 4 }, - ], - }, - { type: "string", maxLength: 3 }, - [{ pathA: ["anyOf", 0, "maxLength"], pathB: ["maxLength"] }] - ); - detail( - "without/with", - { type: "boolean" }, - { anyOf: [{ type: "string" }, { type: "number" }] }, - [{ pathA: [], pathB: ["anyOf"] }] - ); - }); -}); diff --git a/packages/schema/src/tests/util/get-board-files.ts b/packages/schema/src/tests/util/get-board-files.ts deleted file mode 100644 index c89f3a19f92..00000000000 --- a/packages/schema/src/tests/util/get-board-files.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as fs from "fs"; -import { getJsonFiles } from "./get-json-files.js"; - -export function getBoardFiles(directory: string) { - return getJsonFiles(directory).filter((file: fs.PathOrFileDescriptor) => { - try { - const data = JSON.parse(fs.readFileSync(file, "utf-8")); - return Array.isArray(data.edges) && Array.isArray(data.nodes); - } catch (e) { - return false; - } - }); -} diff --git a/packages/schema/src/tests/util/get-json-files.ts b/packages/schema/src/tests/util/get-json-files.ts deleted file mode 100644 index ad235232a39..00000000000 --- a/packages/schema/src/tests/util/get-json-files.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as fs from "fs"; - -export function getJsonFiles( - directory: string, - ignorePatterns: string[] = ["node_modules", ".wireit", "dist"] -): string[] { - const files = fs.readdirSync(directory); - const jsonFiles = files - .filter((file) => file.endsWith(".json")) - .map((file) => `${directory}/${file}`); - const directories = files - .filter( - (file) => - fs.statSync(`${directory}/${file}`).isDirectory() && - !ignorePatterns.includes(file) - ) - .map((file) => `${directory}/${file}`); - return jsonFiles.concat( - directories.flatMap((dir) => getJsonFiles(dir, ignorePatterns)) - ); -} diff --git a/packages/schema/tsconfig.json b/packages/schema/tsconfig.json deleted file mode 100644 index 164018f853a..00000000000 --- a/packages/schema/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "allowSyntheticDefaultImports": true, - "composite": true, - "esModuleInterop": true, - "module": "ESNext", - "moduleResolution": "Node", - "outDir": "dist", - "resolveJsonModule": true, - "rootDir": "src", - "target": "ESNext" - }, - "extends": "@google-labs/tsconfig/base.json", - "include": ["package.json", "breadboard.schema.json", "src/**/*.ts"] -} diff --git a/packages/shared-ui/.eslintrc b/packages/shared-ui/.eslintrc deleted file mode 100644 index 0aae4ceffc5..00000000000 --- a/packages/shared-ui/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "parserOptions": { - "project": ["./tsconfig.json"], - }, -} diff --git a/packages/shared-ui/.gitignore b/packages/shared-ui/.gitignore deleted file mode 100644 index c819d9232a7..00000000000 --- a/packages/shared-ui/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# pyodide assets that we copy into public/. We don't want to check these in -# because they come from NPM. -public/pyodide* -public/python* \ No newline at end of file diff --git a/packages/shared-ui/CHANGELOG.md b/packages/shared-ui/CHANGELOG.md deleted file mode 100644 index 12a91970d2e..00000000000 --- a/packages/shared-ui/CHANGELOG.md +++ /dev/null @@ -1,190 +0,0 @@ -# @breadboard-ai/shared-ui - -## 1.17.0 - -### Minor Changes - -- ab92d99: Plumb edge value data to the GraphRenderer. -- 8f9fddf: Move LightObserver to shared-ui as TopGraphObserver. -- 508c4b3: Plumb through edge highlighting and inner activity. -- 033d656: Teach VE to autosave boards -- f61ccf3: Introduce URL-based component types. -- 12cdec3: Improve tab handling -- 9a9f5c2: Move activity to overlay -- 65c0449: Teach TopGraphObserver about various activity types, especially errors. -- 9c878e2: Start work on a runtime API -- 2f68f71: Move node meta into configurator -- 8540b93: Convert Content to Build API and merge Specialist 2 to Specialist. -- 81eafad: Implement selecting runs and viewing them. -- 4c03455: Introduce Specialist 2 and make Content component support LLM Content. -- d0f99b4: Restyle graph nodes -- 392d7cd: Switch global configurator for per-port -- 3e5f3dc: Add support for "Configured" in property schema editor. -- 77dd2a4: Provide node acitivities out of TopGraphObserver. -- 9fe7d4f: Add multi-tab support -- 8c73da3: Integrate TopGraphObserver into Visual Editor. -- 8572be4: Update UI ready for Runs -- df9b158: Add indicators on edges; use activity log lite -- 93a1d7c: Make "advanced ports" a per-component setting. -- 28e0262: Plumb edge value schema to edge overlay -- a049abf: Move more things into runtime -- ec55e54: Automatically pan/zoom to currently running node -- d7606d3: Implement plumbing for visualizing runs as graphs. -- a6128a3: Switch Visual Editor to use Run API. -- 0088ede: Allow configuring all ports (except start/control) in advanced expansion state. -- d0e894d: Add Edge Value overlay - -### Patch Changes - -- 7fd41bb: Some minor UI tweaks -- 2726cb8: Add minimize/maximize button to overlays -- fe61245: Fix node dimension calculations -- 3d4ca21: Make port preview more robust -- bc967e3: Re-render and emit input event when adding parts in llm-input. -- e6e165d: Show star values in edge inspector -- 981bd9e: Align IDB with Board Servers in nav -- 5bf9e8d: More tab improvements -- e543b2e: Unbreak the app view and only store top graph edge values. -- 7929eee: Reset debugEvent when changing runs -- fd69479: Recover from bad node types -- b8547b8: Fix pinch zoom in read-only mode -- 1f11bf3: Switch follow to using Local Storage -- 77fab49: Account for output ports in node height calc -- 4e00d85: Update URL whenever a tab closes -- 2ccac87: Fix a bug where BGL wouldn't paste into the editor. -- 8efca60: Unclamp llm-output height -- 2ebed5f: Make some minor tweaks to port labels -- 4f4f3ee: Include all ports in configurator -- b84b71b: Fix bug with port selection -- 9254424: Add setting for autosave -- 3e68ec2: Save pending configuration with board -- 5990fd0: Add message for secrets and API keys -- b6eeb3e: Show Activity Marker on graph nodes -- ee56556: Fix comment deletion behavior -- e63b5dd: Polish Specialist and Content. -- 0b78f92: Recognize that sometimes there are no prior runs when initializing RunDetails. -- cbc418b: Ensure that the final node is included in TGO -- e723c09: Couple of minor tweaks -- edefaf9: Add tooltip support -- 409a07e: Restore comment edit ability -- 502e6d5: Show configured nodes as blue rather green -- c36391c: Various small fixes -- 0ab2355: Account for "error" in TGO state. -- f0ce284: Provide accurate run status information via TopGraphObserver. -- cc72dcc: Set runs to be read-only -- 890b8a2: Fix layout reset bug -- 1ad3001: Show configuration previews underneath ports -- 863c3e8: Remove the spurious null-coalescing operator. -- 77d9497: Restore Activity Log -- 09b1a4e: Generate friendlier ID for Graph-based component types. -- 3abc5f6: Teach node-selector to remember search value. -- cac51cb: Teach runtime about tab types -- 679119f: Remove auto-submit machinery -- 852160e: Allow overlays to move & resize -- 71b8727: Teach the sidebar not to jump in vertical mode. -- 40988de: Teach SecretsHelper about the timing of secrets-related events. -- Updated dependencies [49e2740] -- Updated dependencies [54c8197] -- Updated dependencies [703f17d] -- Updated dependencies [8d06f3c] -- Updated dependencies [6136d87] -- Updated dependencies [cb8c99a] -- Updated dependencies [2f1b85c] -- Updated dependencies [4dadf16] -- Updated dependencies [c145fdd] -- Updated dependencies [226be62] -- Updated dependencies [8f9fddf] -- Updated dependencies [2fa05f0] -- Updated dependencies [f61ccf3] -- Updated dependencies [e61fa66] -- Updated dependencies [f71bcfb] -- Updated dependencies [a104fa7] -- Updated dependencies [8a1b8c4] -- Updated dependencies [3188607] -- Updated dependencies [9797718] -- Updated dependencies [8540b93] -- Updated dependencies [81eafad] -- Updated dependencies [4c03455] -- Updated dependencies [3137076] -- Updated dependencies [157c31e] -- Updated dependencies [4cc71ee] -- Updated dependencies [8330f0c] -- Updated dependencies [a039d2e] -- Updated dependencies [1423647] -- Updated dependencies [9783ba8] -- Updated dependencies [6cdf20c] -- Updated dependencies [f63a497] -- Updated dependencies [aafec7f] -- Updated dependencies [1ad3001] -- Updated dependencies [91fe8bb] -- Updated dependencies [100fc95] -- Updated dependencies [cab83ce] -- Updated dependencies [e19f046] -- Updated dependencies [5834c81] -- Updated dependencies [d7606d3] -- Updated dependencies [0ef793f] -- Updated dependencies [84ca649] -- Updated dependencies [d9fd0ab] -- Updated dependencies [a6128a3] - - @breadboard-ai/build@0.10.0 - - @google-labs/breadboard@0.27.0 - - @google-labs/breadboard-schema@1.8.0 - - @breadboard-ai/data-store@0.2.3 - -## 1.16.1 - -### Patch Changes - -- fa8a752: Fix a few nagging bugs in the Component Configuration view. -- 125cf75: Fix bug relating to input events with Google Drive input widgets -- Updated dependencies [bbcdd2d] -- Updated dependencies [9ed58cf] -- Updated dependencies [7f2ef33] -- Updated dependencies [7d46a63] -- Updated dependencies [bac2e35] -- Updated dependencies [ec2fedd] - - @breadboard-ai/build@0.9.1 - - @google-labs/breadboard@0.26.0 - - @breadboard-ai/data-store@0.2.2 - -## 1.16.0 - -### Minor Changes - -- cacd8e2: Introduce HTML preview for llm-output. -- 001b250: Add support for unclamped outputs -- de90fb7: Extract UI to packages/shared-ui -- 28895c3: Add support for inline controls - -### Patch Changes - -- 49b3612: Restore preview functionality -- d799af1: Apply some polish to .app view -- c1e21f7: Move configuration to inline controls -- 9998938: Configure connection server URL via environment variable -- Updated dependencies [cc5f4b6] -- Updated dependencies [49b3612] -- Updated dependencies [e0dccfe] -- Updated dependencies [6404cb3] -- Updated dependencies [9ad0524] -- Updated dependencies [a4301e6] -- Updated dependencies [7fdd660] -- Updated dependencies [a940b87] -- Updated dependencies [b201e07] -- Updated dependencies [15b5659] -- Updated dependencies [374ea85] -- Updated dependencies [0296c89] -- Updated dependencies [a34bb69] -- Updated dependencies [534d67e] -- Updated dependencies [c397d53] -- Updated dependencies [f93ec06] -- Updated dependencies [398bf4f] -- Updated dependencies [7de241c] -- Updated dependencies [a424c92] -- Updated dependencies [c2cd40d] -- Updated dependencies [262cefd] -- Updated dependencies [79d709c] - - @breadboard-ai/build@0.9.0 - - @google-labs/breadboard@0.25.0 - - @breadboard-ai/data-store@0.2.1 - - @google-labs/breadboard-schema@1.7.0 diff --git a/packages/shared-ui/README.md b/packages/shared-ui/README.md deleted file mode 100644 index af47785ec77..00000000000 --- a/packages/shared-ui/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Breadboard Shared UI - -This is the package that contains Web Components that are shared between the Visual Editor and Board Server. diff --git a/packages/shared-ui/package.json b/packages/shared-ui/package.json deleted file mode 100644 index 55157f7c13b..00000000000 --- a/packages/shared-ui/package.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "name": "@breadboard-ai/shared-ui", - "version": "1.17.0", - "description": "Shared UI components for Breadboard", - "main": "./dist/index.js", - "exports": { - ".": { - "default": "./dist/index.js", - "types": "./dist/index.d.ts" - }, - "./elements/connection/connection-broker.ts": { - "default": "./dist/elements/connection/connection-broker.js", - "types": "./dist/elements/connection/connection-broker.d.ts" - }, - "./editor": { - "types": "./dist/elements/editor/editor.d.ts", - "default": "./dist/elements/editor/editor.js" - } - }, - "types": "dist/index.d.ts", - "type": "module", - "scripts": { - "prepack": "npm run build", - "build": "wireit", - "build:tsc": "wireit" - }, - "wireit": { - "build": { - "dependencies": [ - "../breadboard:build", - "../build:build", - "../data-store:build", - "../schema:build", - "build:tsc" - ] - }, - "typescript-files-and-deps": { - "dependencies": [ - "../breadboard:build:tsc", - "../build:build:tsc", - "../data-store:build:tsc", - "../schema:build:tsc" - ], - "files": [ - "src/**/*.ts", - "tsconfig.json", - "../../core/tsconfig/base.json" - ] - }, - "build:tsc": { - "command": "tsc -b --pretty", - "env": { - "FORCE_COLOR": "1" - }, - "dependencies": [ - "typescript-files-and-deps" - ], - "files": [], - "output": [ - "dist/", - "!dist/**/*.min.js{,.map}" - ], - "clean": "if-file-deleted" - } - }, - "repository": { - "directory": "packages/shared-ui", - "type": "git", - "url": "git+https://github.com/breadboard-ai/breadboard.git" - }, - "files": [ - "dist/" - ], - "keywords": [], - "author": "Google Labs Team", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/breadboard-ai/breadboard/issues" - }, - "homepage": "https://github.com/breadboard-ai/breadboard/tree/main/packages/shared-ui#readme", - "devDependencies": { - "@ava/typescript": "^4.0.0", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@google-labs/tsconfig": "^0.0.1", - "@types/markdown-it": "^14.1.2", - "@types/node": "^22.0.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "ava": "^5.2.0", - "dotenv": "^16.4.5", - "tsx": "^4.19.1", - "typescript": "^5.6.2", - "vite": "^5.4.8", - "vite-plugin-full-reload": "^1.2.0", - "vite-plugin-watch-and-run": "^1.7.0", - "vitest": "^2.1.1" - }, - "dependencies": { - "@breadboard-ai/build": "^0.10.0", - "@breadboard-ai/data-store": "^0.2.3", - "@codemirror/autocomplete": "^6.18.1", - "@codemirror/commands": "^6.6.2", - "@codemirror/lang-javascript": "^6.2.2", - "@dagrejs/dagre": "^1.1.4", - "@google-labs/breadboard": "^0.27.0", - "@google-labs/breadboard-schema": "^1.8.0", - "@lit/context": "^1.1.2", - "@lit/task": "^1.0.1", - "@types/gapi": "^0.0.47", - "@types/gapi.drive": "^0.0.9", - "@types/google.picker": "^0.0.42", - "ajv": "^8.17.1", - "codemirror": "^6.0.1", - "idb": "^8.0.0", - "idb-keyval": "^6.2.1", - "lit": "^3.2.0", - "markdown-it": "^14.1.0", - "pixi.js": "^8.4.1" - } -} diff --git a/packages/shared-ui/src/constants/constants.ts b/packages/shared-ui/src/constants/constants.ts deleted file mode 100644 index e4c1c78c876..00000000000 --- a/packages/shared-ui/src/constants/constants.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export const MAIN_BOARD_ID = "Main board"; diff --git a/packages/shared-ui/src/contexts/contexts.ts b/packages/shared-ui/src/contexts/contexts.ts deleted file mode 100644 index 60480276efa..00000000000 --- a/packages/shared-ui/src/contexts/contexts.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export { environmentContext, type Environment } from "./environment.js"; -export { settingsHelperContext } from "./settings-helper.js"; diff --git a/packages/shared-ui/src/contexts/environment.ts b/packages/shared-ui/src/contexts/environment.ts deleted file mode 100644 index efaaf285831..00000000000 --- a/packages/shared-ui/src/contexts/environment.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createContext } from "@lit/context"; -import { InputPlugin } from "../plugins/input-plugin.js"; - -export interface Environment { - connectionServerUrl: string | undefined; - connectionRedirectUrl: string; - plugins: { - input: InputPlugin[]; - }; -} - -export const environmentContext = createContext("bb-environment"); diff --git a/packages/shared-ui/src/directives/markdown.ts b/packages/shared-ui/src/directives/markdown.ts deleted file mode 100644 index fb4de81d3cd..00000000000 --- a/packages/shared-ui/src/directives/markdown.ts +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { noChange } from "lit"; -import { - Directive, - DirectiveParameters, - Part, - directive, -} from "lit/directive.js"; -import { unsafeHTML } from "lit/directives/unsafe-html.js"; -import MarkdownIt from "markdown-it"; - -class MarkdownDirective extends Directive { - #markdownIt = MarkdownIt({ - highlight: (str, lang) => { - if (lang !== "html") { - return str; - } - return ``; - }, - }); - #lastValue: string | null = null; - - #escapeSrcdoc = (str: string) => { - const htmlEntities: Record = { - "&": "&", - "<": "<", - ">": ">", - '"': """, - "'": "'", - }; - - return str.replace(/[&<>"']/g, (char) => htmlEntities[char]); - }; - - update(_part: Part, [value]: DirectiveParameters) { - if (this.#lastValue === value) { - return noChange; - } - - this.#lastValue = value; - return this.render(value); - } - - /** - * Renders the markdown string to HTML using MarkdownIt. - * - * Note: MarkdownIt doesn't enable HTML in its output, so we render the - * value directly without further sanitization. - * @see https://github.com/markdown-it/markdown-it/blob/master/docs/security.md - */ - render(value: string) { - const htmlString = this.#markdownIt.render(value); - return unsafeHTML(htmlString); - } -} - -export const markdown = directive(MarkdownDirective); diff --git a/packages/shared-ui/src/elements/activity-log/activity-log-lite.ts b/packages/shared-ui/src/elements/activity-log/activity-log-lite.ts deleted file mode 100644 index 6939d45f91d..00000000000 --- a/packages/shared-ui/src/elements/activity-log/activity-log-lite.ts +++ /dev/null @@ -1,1012 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { - isLLMContent, - isLLMContentArray, - type ErrorObject, - type Schema, -} from "@google-labs/breadboard"; -import { - LitElement, - html, - css, - nothing, - type HTMLTemplateResult, - type PropertyValues, -} from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { map } from "lit/directives/map.js"; -import { until } from "lit/directives/until.js"; -import { type Ref, createRef, ref } from "lit/directives/ref.js"; -import { - EdgeLogEntry, - LogEntry, - TopGraphRunResult, - type UserInputConfiguration, - type UserMessage, -} from "../../types/types.js"; -import { InputEnterEvent, RunDownloadEvent } from "../../events/events.js"; -import { classMap } from "lit/directives/class-map.js"; -import { UserInput } from "../input/user-input.js"; -import { - isLLMContentArrayBehavior, - isLLMContentBehavior, -} from "../../utils/index.js"; -import { isImageURL } from "../../utils/llm-content.js"; -import { markdown } from "../../directives/markdown.js"; - -@customElement("bb-activity-log-lite") -export class ActivityLogLite extends LitElement { - @property({ reflect: true }) - logTitle = "Activity Log"; - - @property() - waitingMessage = 'Click "Run Board" to get started'; - - @property() - showLogTitle = false; - - @property({ reflect: true }) - showExtendedInfo = false; - - @property() - showActions = true; - - @property() - start: number = 0; - - @property({ reflect: true }) - neutral = false; - - @property({ reflect: true }) - animateNewItems = false; - - @property({ reflect: true }) - hideEmptyEdges = false; - - @property() - waitingGraphic: UserMessage | null = null; - - @property() - topGraphResult: TopGraphRunResult | null = null; - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: block; - padding-bottom: 60px; - } - - h1 { - width: 100%; - display: flex; - align-items: center; - font: 400 var(--bb-title-medium) / var(--bb-title-line-height-medium) - var(--bb-font-family); - padding: var(--bb-grid-size-2) 0; - margin: 0; - position: sticky; - background: var(--bb-neutral-0); - top: -1px; - z-index: 1; - } - - #controls { - position: sticky; - top: 0; - background: var(--bb-neutral-0); - display: grid; - grid-template-rows: 24px; - row-gap: var(--bb-grid-size-10); - align-items: center; - padding: var(--bb-grid-size-2) var(--bb-grid-size-2); - z-index: 1; - } - - #controls input { - border-radius: var(--bb-grid-size); - border: 1px solid var(--bb-neutral-300); - background: var(--bb-neutral-50); - width: 100%; - padding: var(--bb-grid-size-2); - height: 100%; - } - - #controls input:placeholder-shown { - background: var(--bb-neutral-50) var(--bb-icon-search) calc(100% - 5px) - center / 20px 20px no-repeat; - } - - #activity { - padding: var(--bb-grid-size-2); - } - - #actions { - display: flex; - justify-content: flex-end; - } - - #actions button { - border: none; - margin: 0 0 0 var(--bb-grid-size-8); - padding: 0 var(--bb-grid-size-8) 0 0; - height: 20px; - font: var(--bb-font-label-medium); - color: var(--bb-neutral-600); - transition: color 0.3s cubic-bezier(0, 0, 0.3, 1); - cursor: pointer; - } - - #actions button:focus, - #actions button:hover { - color: var(--bb-neutral-800); - transition-duration: 0.15s; - } - - #jump-to-bottom { - background: transparent var(--bb-icon-arrow-down-48px) right center / 24px - 24px no-repeat; - } - - #actions button:last-of-type { - margin-right: var(--bb-grid-size); - } - - #no-entries { - display: flex; - flex-direction: column; - align-items: center; - padding: var(--bb-grid-size-10) 0; - font: var(--bb-font-title-large); - color: var(--bb-neutral-400); - } - - .node-output { - margin: 0; - } - - .pending-input, - .edge { - padding: var(--bb-grid-size-4) var(--bb-grid-size-2) var(--bb-grid-size-4) - var(--bb-grid-size-16); - position: relative; - } - - .pending-input.newest, - .edge.newest { - animation: fadeAndSlideIn 0.3s cubic-bezier(0, 0, 0.3, 1) forwards; - } - - :host([animatenewitems="false"]) .pending-input.newest, - :host([animatenewitems="false"]) .edge.newest { - animation-duration: 0s; - animation-delay: 0s; - } - - .edge.newest { - margin-bottom: var(--bb-grid-size-16); - } - - :host([hideemptyedges="true"]) .edge.empty { - height: 0; - display: flex; - align-items: center; - color: var(--bb-neutral-600); - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - padding-top: var(--bb-grid-size-2); - padding-bottom: var(--bb-grid-size-2); - } - - .pending-input::before, - .edge::before { - content: ""; - position: absolute; - top: 0; - left: 40px; - height: 100%; - } - - .pending-input::before { - border-left: 1px solid var(--bb-inputs-500); - } - - .edge::before { - border-left: 1px solid var(--bb-boards-500); - } - - :host([neutral="true"]) .pending-input::before, - :host([neutral="true"]) .edge::before { - border-left: 1px solid var(--bb-neutral-300); - } - - .pending-input::after, - .edge::after { - content: ""; - position: absolute; - top: calc(50% - 14px); - left: 26px; - width: 28px; - height: 28px; - border-radius: 50%; - } - - .pending-input.newest::before, - .edge.newest::before { - transform: scaleY(0); - animation: growFromTop 0.3s cubic-bezier(0, 0, 0.3, 1) 0.2s forwards; - } - - .pending-input.newest::after, - .edge.newest::after { - opacity: 0; - animation: fadeAndSlideIn 0.3s cubic-bezier(0, 0, 0.3, 1) 0.4s forwards; - } - - :host([animatenewitems="false"]) .pending-input.newest::before, - :host([animatenewitems="false"]) .edge.newest::before, - :host([animatenewitems="false"]) .pending-input.newest::after, - :host([animatenewitems="false"]) .edge.newest::after { - animation-duration: 0s; - animation-delay: 0s; - } - - .pending-input::after { - background: var(--bb-inputs-300) var(--bb-icon-edit) center center / 20px - 20px no-repeat; - } - - .edge::after { - background: var(--bb-boards-500) var(--bb-icon-value) center center / 20px - 20px no-repeat; - } - - :host([hideemptyedges="true"]) .edge.empty::after { - display: none; - } - - :host([hideemptyedges="false"]) .edge.empty { - min-height: var(--bb-grid-size-14); - } - - .edge.empty.newest::before, - .edge.empty.newest::after { - display: none; - } - - .edge bb-llm-output, - .edge bb-llm-output-array { - margin-bottom: 0; - } - - .pending-input:last-of-type::before, - .edge:last-of-type::before { - height: 50%; - } - - .entry { - position: relative; - border: 1px solid var(--bb-neutral-200); - border-radius: var(--bb-grid-size-5); - padding: var(--bb-grid-size-2) var(--bb-grid-size-3); - width: max(60%, 300px); - animation: fadeAndSlideIn 0.3s cubic-bezier(0, 0, 0.3, 1) forwards; - } - - :host([animatenewitems="false"]) .entry { - animation: none; - } - - .entry.pending::after { - content: ""; - position: absolute; - left: calc(100% + var(--bb-grid-size-2)); - top: calc(50% - 8px); - width: 16px; - height: 16px; - background: url(/images/progress-ui.svg) center center / 16px 16px - no-repeat; - } - - .entry:not(.pending)::after { - content: attr(completed); - position: absolute; - left: calc(100% + var(--bb-grid-size-2)); - top: calc(50% - 8px); - height: 16px; - color: var(--bb-neutral-600); - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - width: auto; - min-width: 150px; - } - - .entry.hidden { - display: none; - } - - .entry { - display: flex; - align-items: flex-start; - list-style: none; - font: var(--bb-font-title-small); - color: var(--bb-neutral-600); - user-select: none; - } - - .entry::before { - content: ""; - width: 20px; - height: 20px; - background: var(--bb-ui-50) var(--bb-icon-generic-node) center center / - 20px 20px no-repeat; - border-radius: 50%; - margin-right: var(--bb-grid-size-2); - } - - .entry.input::before { - background: var(--bb-icon-input) center center / 20px 20px no-repeat; - } - - .entry.output::before { - background: var(--bb-icon-output) center center / 20px 20px no-repeat; - } - - .entry.secret::before { - background: var(--bb-icon-password) center center / 20px 20px no-repeat; - } - - .entry.joiner { - color: var(--bb-joiner-500); - } - - .entry.joiner::before { - background: var(--bb-icon-merge-type) center center / 20px 20px no-repeat; - } - - .entry.specialist { - color: var(--bb-specialist-500); - } - - .entry.specialist::before { - background: var(--bb-icon-smart-toy) center center / 20px 20px no-repeat; - } - - .entry.human, - .entry.user { - color: var(--bb-human-500); - } - - .entry.human::before, - .entry.user::before { - background: var(--bb-icon-human) center center / 20px 20px no-repeat; - } - - .entry.looper { - color: var(--bb-looper-500); - } - - .entry.looper::before { - background: var(--bb-icon-lightbulb) center center / 20px 20px no-repeat; - } - - .entry.joiner { - color: var(--bb-joiner-500); - } - - .entry.joiner::before { - background: var(--bb-icon-merge-type) center center / 20px 20px no-repeat; - } - - .entry.runjavascript { - color: var(--bb-nodes-700); - } - - .entry.runjavascript::before { - background: var(--bb-icon-javascript) center center / 20px 20px no-repeat; - } - - .entry .no-information { - font: var(--bb-font-label-medium); - color: var(--bb-neutral-600); - width: 100%; - text-align: center; - margin-top: var(--bb-grid-size); - } - - .entry summary::-webkit-details-marker { - display: none; - } - - .entry details { - width: 100%; - } - - .entry summary { - list-style: none; - background: #fff var(--bb-icon-unfold-more) right center / 20px 20px - no-repeat; - cursor: pointer; - } - - .entry details[open] summary { - background: #fff var(--bb-icon-unfold-less) right center / 20px 20px - no-repeat; - } - - .entry ul { - margin: 0; - padding: var(--bb-grid-size-2) var(--bb-grid-size-2) var(--bb-grid-size-2) - 1px; - font: 400 var(--bb-title-small) / var(--bb-title-line-height-small) - var(--bb-font-family); - color: var(--bb-neutral-600); - list-style: none; - - display: flex; - flex-direction: column; - } - - .entry li { - line-height: 1.4; - padding: var(--bb-grid-size) 0 var(--bb-grid-size) var(--bb-grid-size-4); - position: relative; - } - - .entry li::before { - content: ""; - height: 100%; - position: absolute; - left: 0; - top: 0; - border-left: 1px solid var(--bb-boards-500); - } - - .entry li:first-of-type::before { - height: 50%; - top: 50%; - } - - .entry li:last-of-type::before { - height: 50%; - } - - .entry li::after { - content: ""; - position: absolute; - left: -4px; - top: calc(50% - 4px); - border-radius: 50%; - width: 8px; - height: 8px; - background: var(--bb-boards-500); - } - - .continue-button { - background: var(--bb-ui-100) var(--bb-icon-resume-blue) 8px 4px / 16px - 16px no-repeat; - color: var(--bb-ui-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4) 0 var(--bb-grid-size-7); - margin: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - } - - .completed-item .title { - display: block; - font: 600 var(--bb-label-medium) / var(--bb-label-line-height-medium) - var(--bb-font-family); - padding: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - } - - .completed-item .description { - display: block; - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - margin: 0 0 var(--bb-grid-size-2) 0; - max-width: 90%; - } - - .error { - display: flex; - background: var(--bb-warning-50); - border: 2px solid var(--bb-warning-100); - padding: var(--bb-grid-size-3); - border-radius: var(--bb-grid-size-2); - color: var(--bb-warning-700); - overflow: auto; - font: var(--bb-font-body-small); - font-family: var(--bb-font-family-mono); - } - - @media (min-width: 700px) { - #controls { - grid-template-rows: 24px; - padding: var(--bb-grid-size-3) var(--bb-grid-size-2) - var(--bb-grid-size-3) 0; - } - - #activity { - padding: var(--bb-grid-size-2) var(--bb-grid-size-2) - var(--bb-grid-size-2) 0; - } - } - - @media (min-width: 1120px) { - #controls { - grid-template-rows: 24px; - padding: var(--bb-grid-size-3) 0; - } - - #controls input { - height: 42px; - } - - #activity { - padding: var(--bb-grid-size-2) 0; - } - } - - @keyframes fadeAndSlideIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } - } - - @keyframes growFromTop { - from { - transform-origin: 0 0; - transform: scale(1, 0); - } - - to { - transform-origin: 0 0; - transform: scale(1, 1); - } - } - `; - - #jumpToBottomAfterUpdated = false; - #formatter = new Intl.DateTimeFormat(navigator.languages, { - month: "long", - day: "numeric", - hour: "numeric", - minute: "2-digit", - hour12: true, - }); - #userInputRef: Ref = createRef(); - #activityRef: Ref = createRef(); - - connectedCallback(): void { - super.connectedCallback(); - - this.#jumpToBottom("instant"); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - - this.animateNewItems = false; - } - - async #renderPendingInput(event: EdgeLogEntry) { - const schema = event.schema as Schema; - if (!schema) { - return html`Unable to render`; - } - - const requiredFields = schema.required ?? []; - - // TODO: Implement support for multiple iterations over the - // same input over a run. Currently, we will only grab the - // first value. - const userInputs: UserInputConfiguration[] = Object.entries( - schema.properties ?? {} - ).reduce((prev, [name, schema]) => { - let value = event.value?.[name]; - if (schema.type === "object") { - if (isLLMContentBehavior(schema)) { - if (!isLLMContent(value)) { - value = undefined; - } - } else { - value = JSON.stringify(value, null, 2); - } - } - - if (schema.type === "array") { - if (isLLMContentArrayBehavior(schema)) { - if (!isLLMContentArray(value)) { - value = undefined; - } - } else { - value = JSON.stringify(value, null, 2); - } - } - - prev.push({ - name, - title: schema.title ?? name, - secret: false, - schema, - configured: false, - required: requiredFields.includes(name), - value, - }); - - return prev; - }, [] as UserInputConfiguration[]); - - const continueRun = () => { - if (!this.#userInputRef.value) { - return; - } - - const outputs = this.#userInputRef.value.processData(true); - if (!outputs) { - return; - } - - this.dispatchEvent( - new InputEnterEvent(event.id!, outputs, /* allowSavingIfSecret */ true) - ); - }; - - return html` { - const isMac = navigator.platform.indexOf("Mac") === 0; - const isCtrlCommand = isMac ? evt.metaKey : evt.ctrlKey; - - if (!(evt.key === "Enter" && isCtrlCommand)) { - return; - } - - continueRun(); - }} - > - `; - } - - async #renderCompletedInputOrOutput(event: EdgeLogEntry) { - const { value, schema } = event; - const type = event.id ? "input" : "output"; - if (!value) { - return html`Unable to render item`; - } - - const properties = schema?.properties ?? {}; - return html`
    - ${Object.entries(value).map(([name, nodeValue]) => { - let value: HTMLTemplateResult | symbol = nothing; - if (typeof nodeValue === "object") { - if (isLLMContentArray(nodeValue)) { - value = html``; - } else if (isLLMContent(nodeValue)) { - if (!nodeValue.parts) { - // Special case for "$metadata" item. - // See https://github.com/breadboard-ai/breadboard/issues/1673 - // TODO: Make this not ugly. - const data = (nodeValue as unknown as { data: unknown }).data; - value = html``; - } - - if (!nodeValue.parts.length) { - value = html`No data provided`; - } - - value = nodeValue.parts.length - ? html`` - : html`No data provided`; - } else if (isImageURL(nodeValue)) { - value = html``; - } else { - value = html``; - } - } else { - let renderableValue: HTMLTemplateResult | symbol = nothing; - const format = properties[name]?.format; - if ( - format && - format === "markdown" && - typeof nodeValue === "string" - ) { - renderableValue = html`${markdown(nodeValue)}`; - } else { - renderableValue = html`${nodeValue !== undefined - ? nodeValue - : "No value provided"}`; - } - - // prettier-ignore - value = html`
    ${renderableValue}
    `; - } - - let title: HTMLTemplateResult | symbol = nothing; - let description: HTMLTemplateResult | symbol = nothing; - if (schema && schema.properties) { - title = html`${schema.properties[name]?.title ?? `Input`}`; - - if (schema.properties[name]?.description) { - description = html`${schema.properties[name]?.description}`; - } - } - - return type === "input" - ? html`
    - - ${value} -
    ` - : html`${value}`; - })} -
    `; - } - - #renderLog(entries: LogEntry[]) { - return html`${map(entries, (entry, idx) => { - const newest = idx === entries.length - 1; - switch (entry.type) { - case "edge": { - const pending = entry.end === null; - - if (entry.id) { - // The "input" edge will have an id - // TODO: Maybe we should just have different types of edges? - if (entry.end !== null) { - return html`
    - ${until(this.#renderCompletedInputOrOutput(entry))} -
    `; - } - return html`
    - ${until(this.#renderPendingInput(entry))} -
    `; - } - - if (entry.value) { - // The "output" edge will have no id, but will have a value. - return html`
    - ${until(this.#renderCompletedInputOrOutput(entry))} -
    `; - } - - return html`
    `; - } - - case "node": { - const { descriptor, end } = entry; - const { type } = descriptor; - const icon = undefined; - - const content: - | HTMLTemplateResult - | Promise - | symbol = nothing; - - const classes: Record = { - entry: true, - pending: end === null, - }; - - classes[type.toLocaleLowerCase()] = true; - classes.pending = end === null; - if (icon) { - classes[icon] = true; - } - - let completed = null; - if (end !== null && this.start !== 0) { - completed = this.#formatter.format(this.start + end); - } - - return html`
    - ${this.showExtendedInfo && entry.activity.length - ? html`
    - ${entry.title()} - ${entry.activity.length - ? html`
      - ${map(entry.activity, (entry) => { - return html`
    • - ${entry.description} -
    • `; - })} -
    ` - : html`No activity`} -
    ` - : html`${entry.title()}`} -
    - ${content}`; - } - - case "error": { - const { error } = entry; - let output = ""; - if (typeof error === "string") { - output = error; - } else { - if ((error.error as Error)?.name === "AbortError") { - console.log("💖 actually aborted"); - } - if (typeof error.error === "string") { - output = error.error; - } else { - let messageOutput = ""; - let errorData = error; - while (typeof errorData === "object") { - if (errorData && "message" in errorData) { - messageOutput += `${errorData.message}\n`; - } - - errorData = errorData.error as ErrorObject; - } - - output = messageOutput; - } - } - - return html`
    ${output}
    `; - } - } - })}`; - } - - #jumpToBottom(behavior: ScrollBehavior = "smooth") { - if (!this.#activityRef.value) { - return; - } - - const entries = - this.#activityRef.value.querySelectorAll(".entry"); - if (entries.length === 0) { - return; - } - - const entry = entries[entries.length - 1]; - if (!entry) { - return; - } - entry.scrollIntoView({ - behavior, - block: "start", - inline: "nearest", - }); - } - - protected willUpdate(changedProperties: PropertyValues): void { - if (!changedProperties.has("topGraphResult")) { - return; - } - - this.#jumpToBottomAfterUpdated = true; - this.animateNewItems = true; - } - - protected updated(): void { - if (!this.#jumpToBottomAfterUpdated) { - return; - } - - this.#jumpToBottomAfterUpdated = false; - requestAnimationFrame(() => { - this.#jumpToBottom(); - }); - } - - render() { - const log = this.topGraphResult?.log || []; - - return html` ${this.showLogTitle - ? html`

    ${this.logTitle}

    ` - : nothing} - ${this.showActions - ? html`
    -
    - ${log.length - ? html`` - : nothing} -
    -
    ` - : html` - ${log.length - ? html`` - : nothing} - `} -
    - ${log.length - ? this.#renderLog(log) - : html`
    - ${this.waitingGraphic - ? html` - - ${this.waitingGraphic?.alt} - ` - : nothing} -

    ${this.waitingMessage}

    -
    `} -
    `; - } -} diff --git a/packages/shared-ui/src/elements/activity-log/activity-log.styles.ts b/packages/shared-ui/src/elements/activity-log/activity-log.styles.ts deleted file mode 100644 index 89f610ccb35..00000000000 --- a/packages/shared-ui/src/elements/activity-log/activity-log.styles.ts +++ /dev/null @@ -1,473 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { css } from "lit"; - -export const styles = css` - :host { - display: block; - background: #fff; - - --padding-x: calc(var(--bb-grid-size) * 4); - --padding-y: var(--bb-grid-size-2); - } - - :host > h1 { - position: sticky; - top: 0; - font: 400 var(--bb-title-medium) / var(--bb-title-line-height-medium) - var(--bb-font-family); - margin: 0 0 var(--bb-grid-size) 0; - padding: var(--bb-grid-size-2) var(--bb-grid-size-4); - background: white; - z-index: 2; - display: flex; - } - - :host > h1 > span { - flex: 1; - } - - :host > h1::after { - content: ""; - width: calc(100% - var(--padding-x) * 2); - height: 1px; - position: absolute; - bottom: var(--bb-grid-size); - left: var(--padding-x); - background: #f6f6f6; - } - - :host > h1 > a, - a.download { - font-size: var(--bb-label-small); - color: var(--bb-neutral-500); - text-decoration: none; - user-select: none; - cursor: pointer; - } - - :host > h1 > a:hover, - :host > h1 > a:active, - a.download:hover, - a.download:active { - color: var(--bb-neutral-700); - } - - #download-container { - display: flex; - justify-content: flex-end; - } - - .activity-entry { - padding: var(--padding-y) 0; - position: relative; - font-size: var(--bb-font-medium); - user-select: none; - } - - :host > .activity-entry { - padding-left: var(--padding-x); - padding-right: var(--padding-x); - } - - :host > .activity-entry:last-of-type { - margin-bottom: 20px; - } - - .activity-entry.error { - color: #cc0000; - user-select: text; - } - - .activity-entry h1 { - font-size: var(--bb-text-regular); - margin: 0; - font-weight: 400; - } - - .activity-entry h1 .newest-task { - font-size: var(--bb-text-medium); - font-weight: 300; - margin-left: var(--bb-grid-size); - } - - .activity-entry::after { - content: ""; - width: calc(var(--bb-grid-size) * 4); - height: calc(var(--bb-grid-size) * 4); - border-radius: 50%; - top: calc(var(--padding-y) + var(--bb-grid-size) - 3px); - left: -2px; - position: absolute; - --background: var(--bb-nodes-400); - } - - :host > .activity-entry::after { - left: calc(var(--padding-x) + 10px); - } - - .activity-entry.icon::after { - width: calc(var(--bb-grid-size) * 7); - height: calc(var(--bb-grid-size) * 7); - left: calc(var(--padding-x) + 3px); - top: calc(var(--padding-y) - var(--bb-grid-size)); - background: #fff var(--node-icon) center center no-repeat; - background-size: 20px 20px; - border: 1px solid #d9d9d9; - } - - .activity-entry::before { - --top: calc(var(--padding-y) + 5px); - content: ""; - width: 2px; - height: 100%; - left: 5px; - top: 0; - height: 100%; - position: absolute; - background: var(--bb-neutral-300); - } - - :host > .activity-entry::before { - left: calc(var(--padding-x) + 17px); - } - - .neural-activity { - width: calc(var(--bb-grid-size) * 4); - height: calc(var(--bb-grid-size) * 4); - border-radius: 50%; - display: inline-block; - margin-left: -2px; - margin-top: -2px; - margin-right: var(--bb-grid-size-2); - position: relative; - z-index: 1; - --background: var(--bb-nodes-400); - } - - .neural-activity:last-of-type { - margin-right: 0; - } - - .neural-activity.error, - .activity-entry.error::after { - --background: var(--bb-warning-600); - } - - .neural-activity.input, - .activity-entry.input::after { - --background: var(--bb-inputs-300); - } - - .neural-activity.secret, - .activity-entry.secret::after { - --background: var(--bb-inputs-300); - } - - .neural-activity.output, - .activity-entry.output::after { - --background: var(--bb-boards-300); - } - - .neural-activity, - .activity-entry::after { - background: radial-gradient( - var(--background) 0%, - var(--background) 50%, - transparent 50% - ); - } - - .neural-activity.pending, - .activity-entry.pending::after { - box-shadow: 0 0 0 4px #3399ff40; - box-sizing: border-box; - background: radial-gradient( - var(--background) 0%, - var(--background) 50%, - transparent 50% - ), - linear-gradient(#3399ff40, #3399ffff); - animation: rotate 1s linear infinite forwards; - } - - .activity-entry:first-of-type::before { - top: var(--top); - height: calc(100% - var(--top)); - } - - .activity-entry:last-of-type::before { - height: var(--top); - } - - .activity-entry:first-of-type:last-of-type::before { - display: none; - } - - .activity-entry > .content { - padding-left: calc(var(--bb-grid-size) * 6); - } - - :host > .activity-entry > .content { - padding-left: calc(var(--bb-grid-size) * 10); - } - - .subgraph-info { - padding: var(--bb-grid-size-2) calc(var(--bb-grid-size) * 4); - } - - .subgraph-info summary { - margin-left: -20px; - display: grid; - grid-template-columns: 20px auto; - align-items: center; - } - - .subgraph-info summary::before { - content: ""; - width: 20px; - height: 20px; - background: var(--bb-icon-arrow-right) center center / 20px 20px no-repeat; - display: inline-block; - margin: -5px 0 0 0; - } - - .subgraph-info[open] > summary::before { - background: var(--bb-icon-arrow-drop-down) -1px 6px / 20px 20px no-repeat; - } - - .subgraph-info[open] > summary { - margin-bottom: -20px; - } - - .activity-summary { - width: fit-content; - position: relative; - } - - .activity-summary::before { - content: ""; - position: absolute; - background: #ededed; - border-radius: 8px; - bottom: 6px; - right: 2px; - left: 1px; - top: 1px; - z-index: 0; - } - - .subgraph-info[open] > summary .activity-summary { - position: absolute; - pointer-events: none; - opacity: 0; - } - - h1[data-message-id] { - cursor: pointer; - opacity: 0.65; - transition: opacity 0.3s cubic-bezier(0, 0, 0.3, 1); - } - - h1[data-message-id]:hover, - h1[data-message-id]:focus { - opacity: 1; - transition-duration: 0.1s; - } - - summary::-webkit-details-marker { - display: none; - } - - summary { - list-style: none; - } - - .node-output details { - padding: var(--bb-grid-size-2); - } - - .node-output summary { - font-size: var(--bb-text-small); - margin: var(--bb-grid-size-2) 0; - font-weight: normal; - } - - .node-output details div { - font-size: var(--bb-text-nano); - font-family: var(--bb-font-family-mono); - line-height: 1.65; - } - - .node-output img { - border-radius: var(--bb-grid-size); - display: block; - width: 100%; - border: 1px solid var(--bb-neutral-300); - } - - dl { - margin: 0; - padding: 0; - } - - dd { - display: block; - margin: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - font-size: var(--bb-text-small); - } - - dt { - font-size: var(--bb-text-medium); - } - - dt .value { - white-space: pre-line; - border-radius: var(--bb-grid-size); - padding: var(--bb-input-padding, var(--bb-grid-size-2)); - user-select: auto; - } - - dt .value.output * { - margin: var(--bb-grid-size) 0; - } - - dt .value.input h1, - dt .value.output h1 { - font-size: var(--bb-title-large); - margin: var(--bb-grid-size-3) 0 var(--bb-grid-size) 0; - } - - dt .value.input h2, - dt .value.output h2 { - font-size: var(--bb-title-medium); - margin: var(--bb-grid-size-3) 0 var(--bb-grid-size) 0; - } - - dt .value.input h3, - dt .value.input h4, - dt .value.input h5, - dt .value.output h3, - dt .value.output h4, - dt .value.output h5 { - font-size: var(--bb-title-small); - margin: 0 0 var(--bb-grid-size-2) 0; - } - - dt .value.input p, - dt .value.output p { - font-size: var(--bb-body-medium); - margin: 0 0 var(--bb-grid-size-2) 0; - white-space: pre-line; - } - - dt .value.input { - border: 1px solid var(--bb-neutral-300); - white-space: pre-line; - max-height: 300px; - overflow-y: auto; - scrollbar-gutter: stable; - } - - dt .value.input.markdown, - dt .value.output.markdown { - white-space: normal; - line-height: 1.5; - user-select: text; - } - - dt .value.input.markdown p, - dt .value.output.markdown p { - white-space: normal; - } - - dt .value.input :first-child, - dt .value.output :first-child { - margin-top: 0; - } - - pre { - display: inline-block; - margin: 0; - } - - #click-run { - font-size: var(--bb-text-small); - color: #9c9c9c; - padding: 0 var(--padding-x) var(--padding-y) var(--padding-x); - } - - .user-required { - position: relative; - } - - .user-required::before { - content: ""; - position: absolute; - left: -20px; - top: -10px; - right: -10px; - bottom: -10px; - background: var(--bb-selected-color); - border-radius: var(--bb-grid-size); - animation: fadeOut 1s ease-out forwards; - } - - .continue-button { - background: var(--bb-continue-color) var(--bb-icon-resume-blue) 8px 4px / - 16px 16px no-repeat; - color: var(--bb-ui-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4) 0 var(--bb-grid-size-7); - margin: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - } - - @keyframes slideIn { - from { - translate: 0 -5px; - opacity: 0; - } - - to { - translate: 0 0; - opacity: 1; - } - } - - @keyframes rotate { - from { - transform: rotate(0); - } - - to { - transform: rotate(360deg); - } - } - - @keyframes fadeOut { - 0% { - opacity: 0; - } - - 25% { - opacity: 0.15; - } - - 50% { - opacity: 0; - } - - 75% { - opacity: 0.15; - } - - 100% { - opacity: 0; - } - } -`; diff --git a/packages/shared-ui/src/elements/activity-log/activity-log.ts b/packages/shared-ui/src/elements/activity-log/activity-log.ts deleted file mode 100644 index 7339f46090e..00000000000 --- a/packages/shared-ui/src/elements/activity-log/activity-log.ts +++ /dev/null @@ -1,678 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphProvider, - InspectableRun, - InspectableRunEvent, - InspectableRunInputs, - InspectableRunNodeEvent, - InspectableRunSecretEvent, - isLLMContent, - isLLMContentArray, - OutputValues, - Schema, - SerializedRun, -} from "@google-labs/breadboard"; -import { LitElement, html, HTMLTemplateResult, nothing } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { classMap } from "lit/directives/class-map.js"; -import { Ref, createRef, ref } from "lit/directives/ref.js"; -import { InputEnterEvent, InputRequestedEvent } from "../../events/events.js"; -import { map } from "lit/directives/map.js"; -import { styleMap } from "lit/directives/style-map.js"; -import { until } from "lit/directives/until.js"; -import { markdown } from "../../directives/markdown.js"; -import { SETTINGS_TYPE, UserInputConfiguration } from "../../types/types.js"; -import { styles as activityLogStyles } from "./activity-log.styles.js"; -import { SettingsStore } from "../../types/types.js"; -import { UserInput } from "../elements.js"; -import { - isLLMContentArrayBehavior, - isLLMContentBehavior, -} from "../../utils/index.js"; -import { formatError } from "../../utils/format-error.js"; - -@customElement("bb-activity-log") -export class ActivityLog extends LitElement { - @property({ reflect: false }) - run: InspectableRun | null = null; - - @property({ reflect: false }) - inputsFromLastRun: InspectableRunInputs | null = null; - - @property({ reflect: false }) - events: InspectableRunEvent[] | null = null; - - @property({ reflect: true }) - eventPosition = 0; - - @property({ reflect: true }) - logTitle = "Activity Log"; - - @property() - waitingMessage = 'Click "Run Board" to get started'; - - @property({ reflect: true }) - showExtendedInfo = false; - - @property({ reflect: true }) - showLogTitle = true; - - @property() - settings: SettingsStore | null = null; - - @property() - providers: GraphProvider[] = []; - - @property() - providerOps = 0; - - #seenItems = new Set(); - #newestEntry: Ref = createRef(); - #userInputRef: Ref = createRef(); - #isHidden = false; - #serializedRun: SerializedRun | null = null; - #observer = new IntersectionObserver((entries) => { - if (entries.length === 0) { - return; - } - - const [entry] = entries; - if (!entry.rootBounds) { - return; - } - - this.#isHidden = - entry.rootBounds.width === 0 && entry.rootBounds.height === 0; - - if ( - !this.#isHidden && - this.#newestEntry.value && - this.#newestEntry.value.querySelector(".user-required") - ) { - this.#newestEntry.value.scrollIntoView({ - block: "nearest", - inline: "start", - }); - this.#newestEntry.value - .querySelector(".user-required") - ?.addEventListener("animationend", (evt: Event) => { - if (!(evt.target instanceof HTMLElement)) { - return; - } - - evt.target.classList.remove("user-required"); - }); - } - }); - - static styles = activityLogStyles; - - #isImageURL(nodeValue: unknown): nodeValue is { image_url: string } { - if (typeof nodeValue !== "object" || !nodeValue) { - return false; - } - - return "image_url" in nodeValue; - } - - protected updated(): void { - if (!this.#newestEntry.value) { - return; - } - - if (this.#newestEntry.value.querySelector(".user-required")) { - this.dispatchEvent(new InputRequestedEvent()); - } - - this.#newestEntry.value.scrollIntoView({ - block: "nearest", - inline: "start", - }); - } - - connectedCallback(): void { - super.connectedCallback(); - - this.#observer.observe(this); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - - this.#observer.disconnect(); - } - - #createRunInfo(runs: InspectableRun[] = []): HTMLTemplateResult | symbol { - if (runs.length === 0) { - return nothing; - } - - return html`${map(runs, (run) => { - if (run.events.length === 0) { - return nothing; - } - - return html`
    - - ${run.events.map((event, idx) => { - if (event.type !== "node") { - return nothing; - } - - const classes: Record = { - "neural-activity": true, - pending: idx === run.events.length - 1 && run.end === null, - [event.node.descriptor.type]: true, - }; - - return html`
    `; - })}
    -
    - ${map(run.events, (event, idx) => { - if (event.type !== "node") { - return nothing; - } - - const { type } = event.node.descriptor; - - const classes: Record = { - "activity-entry": true, - pending: idx === run.events.length - 1 && run.end === null, - [type]: true, - }; - - return html`
    -
    -

    - ${event.node.description()} -

    - ${this.#createRunInfo(event.runs)} -
    -
    `; - })} -
    `; - })}`; - } - - #getNewestSubtask(runs: InspectableRun[] = []): HTMLTemplateResult | symbol { - if (runs.length === 0) { - return nothing; - } - - const newestRun = runs[runs.length - 1]; - const newestEvent = newestRun.events[newestRun.events.length - 1]; - - if (!newestEvent || newestEvent.type !== "node") { - return nothing; - } - - return html`${newestEvent.node.description()}`; - } - - #download(evt: Event) { - if (!(evt.target instanceof HTMLAnchorElement)) { - return; - } - - if (!this.#serializedRun) { - return; - } - - const data = JSON.stringify(this.#serializedRun, null, 2); - - evt.target.download = `run-${new Date().toISOString()}.json`; - evt.target.href = URL.createObjectURL( - new Blob([data], { type: "application/json" }) - ); - this.#serializedRun = null; - this.requestUpdate(); - } - - async #getRunLog(evt: Event) { - if (!(evt.target instanceof HTMLAnchorElement)) { - return; - } - - if (!this.run || !this.run.serialize) { - return; - } - - if (evt.target.href) { - URL.revokeObjectURL(evt.target.href); - } - - evt.target.textContent = "Creating Download..."; - - this.#serializedRun = await this.run.serialize(); - this.requestUpdate(); - } - - async #renderSecretInput(idx: number, event: InspectableRunSecretEvent) { - const userInputs: UserInputConfiguration[] = event.keys.reduce( - (prev, key) => { - const schema: Schema = { - properties: { - secret: { - title: key, - description: `Enter ${key}`, - type: "string", - }, - }, - }; - - const savedSecret = - this.settings?.getSection(SETTINGS_TYPE.SECRETS).items.get(key) ?? - null; - - let value = undefined; - if (savedSecret) { - value = savedSecret.value; - } - - prev.push({ - name: key, - title: schema.title ?? key, - secret: true, - schema, - configured: false, - required: true, - value, - }); - - return prev; - }, - [] as UserInputConfiguration[] - ); - - // If there aren't any secrets to enter, we can skip rendering the control. - if (userInputs.every((secret) => secret.value !== undefined)) { - return html``; - } - - const continueRun = () => { - if (!this.#userInputRef.value) { - return; - } - - const outputs = this.#userInputRef.value.processData(true); - if (!outputs) { - return; - } - - for (const [key, value] of Object.entries(outputs)) { - if (typeof value !== "string") { - console.warn( - `Expected secret as string, instead received ${typeof value}` - ); - continue; - } - - // Dispatch an event for each secret received. - this.dispatchEvent( - new InputEnterEvent( - key, - { secret: value }, - /* allowSavingIfSecret */ true - ) - ); - } - }; - - return html`
    -

    ${event.type}

    - ${event.keys.map((id) => { - if (id.startsWith("connection:")) { - return html``; - } else { - return html` { - const isMac = navigator.platform.indexOf("Mac") === 0; - const isCtrlCommand = isMac ? evt.metaKey : evt.ctrlKey; - - if (!(evt.key === "Enter" && isCtrlCommand)) { - return; - } - - continueRun(); - }} - >`; - } - })} - - -
    `; - } - - async #renderPendingInput(idx: number, event: InspectableRunNodeEvent) { - const { inputs, node } = event; - const nodeSchema = await node.describe(inputs); - const descriptor = node.descriptor; - const schema = nodeSchema?.outputSchema || inputs.schema; - const requiredFields = (inputs.schema as Schema).required ?? []; - - // TODO: Implement support for multiple iterations over the - // same input over a run. Currently, we will only grab the - // first value. - const values = this.inputsFromLastRun?.get(descriptor.id)?.[0]; - const userInputs: UserInputConfiguration[] = Object.entries( - schema.properties ?? {} - ).reduce((prev, [name, schema]) => { - let value = values ? values[name] : undefined; - if (schema.type === "object") { - if (isLLMContentBehavior(schema)) { - if (!isLLMContent(value)) { - value = undefined; - } - } else { - value = JSON.stringify(value, null, 2); - } - } - - if (schema.type === "array") { - if (isLLMContentArrayBehavior(schema)) { - if (!isLLMContentArray(value)) { - value = undefined; - } - } else { - value = JSON.stringify(value, null, 2); - } - } - - prev.push({ - name, - title: schema.title ?? name, - secret: false, - schema, - configured: false, - required: requiredFields.includes(name), - value, - }); - - return prev; - }, [] as UserInputConfiguration[]); - - const continueRun = () => { - if (!this.#userInputRef.value) { - return; - } - - const outputs = this.#userInputRef.value.processData(true); - if (!outputs) { - return; - } - - this.dispatchEvent( - new InputEnterEvent( - descriptor.id, - outputs, - /* allowSavingIfSecret */ true - ) - ); - }; - - return html`
    -

    - ${node.title()} -

    - { - const isMac = navigator.platform.indexOf("Mac") === 0; - const isCtrlCommand = isMac ? evt.metaKey : evt.ctrlKey; - - if (!(evt.key === "Enter" && isCtrlCommand)) { - return; - } - - continueRun(); - }} - > - -
    `; - } - - async #renderDoneInputOrOutput(event: InspectableRunNodeEvent) { - const { node, inputs, outputs } = event; - const allPorts = await node.ports(inputs, outputs as OutputValues); - const type = node.descriptor.type; - const isOutput = type === "output"; - const portList = isOutput ? allPorts.inputs : allPorts.outputs; - - return html`
    - ${portList.ports.map((port) => { - if (port.star) return nothing; - if (isOutput && port.name === "schema") return nothing; - const nodeValue = port.value; - let value: HTMLTemplateResult | symbol = nothing; - if (typeof nodeValue === "object") { - if (isLLMContentArray(nodeValue)) { - value = html``; - } else if (isLLMContent(nodeValue)) { - if (!nodeValue.parts) { - // Special case for "$metadata" item. - // See https://github.com/breadboard-ai/breadboard/issues/1673 - // TODO: Make this not ugly. - const data = (nodeValue as unknown as { data: unknown }).data; - value = html``; - } - - if (!nodeValue.parts.length) { - value = html`No data provided`; - } - - value = nodeValue.parts.length - ? html`` - : html`No data provided`; - } else if (this.#isImageURL(nodeValue)) { - value = html``; - } else { - value = html``; - } - } else { - let renderableValue: HTMLTemplateResult | symbol = nothing; - if ( - port.schema.format === "markdown" && - typeof nodeValue === "string" - ) { - renderableValue = html`${markdown(nodeValue)}`; - } else { - renderableValue = html`${nodeValue !== undefined - ? nodeValue - : "No value provided"}`; - } - - // prettier-ignore - value = html`
    ${renderableValue}
    `; - } - - return html`
    ${port.title}
    -
    ${value}
    `; - })} -
    `; - } - - render() { - if (!this.events || this.#seenItems.size > this.events.length) { - this.#seenItems.clear(); - } - const showLogDownload = this.run && this.run.serialize; - - const downloadReady = !!this.#serializedRun; - - return html` - ${this.showLogTitle - ? html`

    - ${this.logTitle}${showLogDownload - ? downloadReady - ? html` this.#download(evt)} - >Click to Download` - : html` this.#getRunLog(evt)} - >Download` - : nothing} -

    ` - : html`${showLogDownload - ? downloadReady - ? html`` - : html`` - : nothing}`} - ${this.events && this.events.length - ? this.events.map((event, idx) => { - const isNew = this.#seenItems.has(event.id); - this.#seenItems.add(event.id); - - let content: - | HTMLTemplateResult - | Promise - | symbol = nothing; - switch (event.type) { - case "node": { - const { node, end } = event; - const { type } = node.descriptor; - // `end` is null if the node is still running - // that is, the `nodeend` for this node hasn't yet - // been received. - if (end === null) { - if (type === "input") { - content = this.#renderPendingInput(idx, event); - break; - } - - if (event.hidden) { - content = html`

    Working

    `; - } else { - content = html` -

    - ${node.title()} ${this.#getNewestSubtask(event.runs)} -

    - ${this.#createRunInfo(event.runs)} - `; - } - } else { - let additionalData: Promise | symbol = - nothing; - if (type === "input" || type === "output") { - additionalData = this.#renderDoneInputOrOutput(event); - } - - content = html`
    -

    - ${node.title()} -

    - ${until(additionalData)} ${this.#createRunInfo(event.runs)} -
    `; - break; - } - break; - } - - case "secret": { - if (event.end !== null) { - return nothing; - } - - content = this.#renderSecretInput(idx, event); - break; - } - - case "error": { - const output = formatError(event.error); - content = html`${output}`; - break; - } - - default: { - return nothing; - } - } - - const classes: Record = { - "activity-entry": true, - new: isNew, - [event.type]: true, - }; - - if (event.type === "node") { - classes[event.node.descriptor.type] = true; - } - - const styles: Record = {}; - if ( - event.type === "node" && - event.node.descriptor.metadata && - event.node.descriptor.metadata.visual && - typeof event.node.descriptor.metadata.visual === "object" - ) { - const visual = event.node.descriptor.metadata.visual as Record< - string, - string - >; - if (visual.icon) { - classes.icon = true; - styles["--node-icon"] = `url(${visual.icon})`; - } - } - - return html`
    -
    ${until(content)}
    -
    `; - }) - : html`
    ${this.waitingMessage}
    `} - `; - } -} diff --git a/packages/shared-ui/src/elements/board-details/board-details.ts b/packages/shared-ui/src/elements/board-details/board-details.ts deleted file mode 100644 index fe10cee3cfd..00000000000 --- a/packages/shared-ui/src/elements/board-details/board-details.ts +++ /dev/null @@ -1,340 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { LitElement, html, css, nothing } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { BoardInfoUpdateEvent } from "../../events/events.js"; -import { Ref, createRef, ref } from "lit/directives/ref.js"; -import { classMap } from "lit/directives/class-map.js"; -import { GraphMetadata } from "@google-labs/breadboard-schema/graph.js"; - -const STORAGE_PREFIX = "bb-board-details"; - -@customElement("bb-board-details") -export class BoardDetails extends LitElement { - @property() - expanded = false; - - @property() - readOnly = false; - - @property() - boardTitle: string | null = null; - - @property() - boardVersion: string | null = null; - - @property() - boardDescription: string | null = null; - - @property() - boardPublished: boolean | null = null; - - @property() - boardIsTool: boolean | null = null; - - @property() - boardHelp: GraphMetadata["help"] | null = null; - - @property() - subGraphId: string | null = null; - - #formRef: Ref = createRef(); - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: block; - border-bottom: 1px solid var(--bb-neutral-300); - background: var(--bb-neutral-0); - } - - :host > h1 { - position: sticky; - margin: 0 0 var(--bb-grid-size) 0; - top: 0; - z-index: 2; - } - - #unfold { - cursor: pointer; - width: 100%; - display: grid; - grid-template-columns: auto min-content; - align-items: center; - border: none; - background: #fff; - font: 400 var(--bb-title-medium) / var(--bb-title-line-height-medium) - var(--bb-font-family); - padding: var(--bb-grid-size-2) var(--bb-grid-size-4); - text-align: left; - } - - #unfold::after { - content: ""; - width: 20px; - height: 20px; - background: #fff var(--bb-icon-unfold-more) center center / 20px 20px - no-repeat; - justify-self: end; - } - - #unfold.visible::after { - background: #fff var(--bb-icon-unfold-less) center center / 20px 20px - no-repeat; - } - - .split { - display: grid; - grid-template-columns: 1fr 1fr; - column-gap: var(--bb-grid-size-2); - align-items: center; - } - - .split div { - display: flex; - align-items: center; - } - - .split label { - margin-right: var(--bb-grid-size); - } - - form { - display: none; - grid-template-rows: 16px 28px; - row-gap: var(--bb-grid-size-2); - padding: 0 var(--bb-grid-size-4) var(--bb-grid-size-4) - var(--bb-grid-size-4); - } - - form.visible { - display: grid; - } - - form[disabled] > * { - opacity: 0.8; - } - - input[type="text"], - textarea, - select { - padding: var(--bb-grid-size); - font: 400 var(--bb-body-medium) / var(--bb-body-line-height-medium) - var(--bb-font-family); - border: 1px solid var(--bb-neutral-300); - border-radius: var(--bb-grid-size); - } - - input[type="checkbox"] { - margin: 0; - } - - textarea { - resize: none; - field-sizing: content; - max-height: 300px; - } - - label { - font: 400 var(--bb-label-medium) / var(--bb-label-line-height-medium) - var(--bb-font-family); - } - - .help { - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - padding: 0 var(--bb-grid-size-2) 0 var(--bb-grid-size-7); - background: var(--bb-neutral-100) var(--bb-icon-help) 4px center / 20px - 20px no-repeat; - display: inline-flex; - border-radius: 50px; - height: 24px; - align-items: center; - text-decoration: none; - color: var(--bb-neutral-800); - margin: 0 var(--bb-grid-size-4) var(--bb-grid-size-4) - var(--bb-grid-size-4); - } - - .help:hover, - .help:focus { - background-color: var(--bb-neutral-300); - } - `; - - connectedCallback(): void { - super.connectedCallback(); - - const isExpanded = globalThis.sessionStorage.getItem( - `${STORAGE_PREFIX}-expanded` - ); - - this.expanded = isExpanded === "true"; - } - - #emitUpdatedInfo() { - const form = this.#formRef.value; - if (!form) { - return; - } - - if (!form.checkValidity()) { - form.reportValidity(); - return; - } - - const data = new FormData(form); - if ( - !(data.has("title") && data.has("version") && data.has("description")) - ) { - return; - } - - this.dispatchEvent( - new BoardInfoUpdateEvent( - data.get("title") as string, - data.get("version") as string, - data.get("description") as string, - data.get("status") as "published" | "draft" | null, - data.get("tool") === "on", - this.subGraphId - ) - ); - } - - render() { - return html`

    - -

    - -
    { - evt.preventDefault(); - evt.stopImmediatePropagation(); - - this.#emitUpdatedInfo(); - }} - @keydown=${(evt: KeyboardEvent) => { - if (evt.key !== "Enter") { - return; - } - - this.#emitUpdatedInfo(); - }} - @submit=${(evt: Event) => { - evt.preventDefault(); - }} - > - - - - - - - - - -
    - ${this.boardPublished !== null - ? html` -
    - - -
    - ` - : nothing} - ${this.boardIsTool !== null - ? html` -
    - - -
    - ` - : nothing} -
    -
    - - ${this.boardHelp - ? html` ${this.boardHelp.description ?? "Read more"}` - : nothing} `; - } -} diff --git a/packages/shared-ui/src/elements/connection/connection-broker.ts b/packages/shared-ui/src/elements/connection/connection-broker.ts deleted file mode 100644 index 3a983a8be8b..00000000000 --- a/packages/shared-ui/src/elements/connection/connection-broker.ts +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GrantResponse, - oauthTokenBroadcastChannelName, - type OAuthStateParameter, -} from "./connection-common.js"; - -export class ConnectionBroker extends HTMLElement { - constructor() { - super(); - this.attachShadow({ mode: "open" }); - } - - async connectedCallback() { - const shadow = this.shadowRoot!; - - // Unpack the state parameter. - const thisUrl = new URL(window.location.href); - const stateStr = thisUrl.searchParams.get("state"); - if (!stateStr) { - shadow.innerHTML = ` -

    Error: No "state" parameter could be found in the URL. - Please close this window and try to sign in again.

    - `; - return; - } - let state: OAuthStateParameter; - try { - state = JSON.parse(stateStr); - } catch (e) { - shadow.innerHTML = ` -

    Error: "state" contained invalid JSON. - Please close this window and try to sign in again.

    - `; - console.error(e); - return; - } - - // Figure out where we are going to send the response. - const nonce = state.nonce; - if (!nonce) { - shadow.innerHTML = ` -

    Error: No "nonce" parameter could be found in "state". - Please close this window and try to sign in again.

    - `; - return; - } - const channelName = oauthTokenBroadcastChannelName(nonce); - const channel = new BroadcastChannel(channelName); - - // Unpack the data needed to call the token grant API. - const connectionId = state.connectionId; - if (!connectionId) { - shadow.innerHTML = ` -

    Error: No "connection_id" parameter could be found in "state". - Please close this window and try to sign in again.

    - `; - return; - } - const code = thisUrl.searchParams.get("code"); - if (!code) { - shadow.innerHTML = ` -

    Error: No "code" parameter could be found in the URL. - Please close this window and try to sign in again.

    - `; - return; - } - - // Call the token grant API. - if (!import.meta.env.VITE_CONNECTION_SERVER_URL) { - shadow.innerHTML = `

    Error: Could not find a grant URL for this origin.

    `; - return; - } - const grantUrl = new URL("grant", import.meta.env.VITE_CONNECTION_SERVER_URL); - grantUrl.searchParams.set("connection_id", connectionId); - grantUrl.searchParams.set("code", code); - grantUrl.searchParams.set( - "redirect_path", - new URL(window.location.href).pathname - ); - const response = await fetch(grantUrl, { credentials: "include" }); - if (!response.ok) { - const text = await response.text().catch((e) => `Text read error: ${e}`); - shadow.innerHTML = ` -

    Error: Connection service returned HTTP ${response.status}.

    -
    ${text}
    `; - return; - } - let grantResponse: GrantResponse; - try { - grantResponse = await response.json(); - } catch (e) { - shadow.innerHTML = - "

    Error: Could not read JSON response from backend.

    "; - console.error(e); - return; - } - - // Send the grant response back to the originating tab and close up shop. - channel.postMessage(grantResponse); - channel.close(); - window.close(); - } -} - -customElements.define("bb-connection-broker", ConnectionBroker); diff --git a/packages/shared-ui/src/elements/connection/connection-common.ts b/packages/shared-ui/src/elements/connection/connection-common.ts deleted file mode 100644 index bf636192ca5..00000000000 --- a/packages/shared-ui/src/elements/connection/connection-common.ts +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export interface OAuthStateParameter { - nonce: string; - connectionId: string; -} - -export function oauthTokenBroadcastChannelName(nonce: string): string { - return `oauth_token_${nonce}`; -} - -// IMPORTANT: Keep in sync with -// breadboard/packages/connection-server/src/api/grant.ts -export type GrantResponse = - | { error: string } - | { - error?: undefined; - access_token: string; - expires_in: number; - refresh_token: string; - }; - -export interface TokenGrant { - client_id: string; - access_token: string; - expires_in: number; - refresh_token: string; - issue_time: number; -} - -export type RefreshResponse = - | { error: string } - | { - error?: undefined; - access_token: string; - expires_in: number; - }; - -// IMPORTANT: Keep in sync with -// breadboard/packages/connection-server/src/api/refresh.ts -export interface RefreshRequest { - connection_id: string; - refresh_token: string; -} diff --git a/packages/shared-ui/src/elements/connection/connection-input.ts b/packages/shared-ui/src/elements/connection/connection-input.ts deleted file mode 100644 index 7245f242a4d..00000000000 --- a/packages/shared-ui/src/elements/connection/connection-input.ts +++ /dev/null @@ -1,143 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { consume } from "@lit/context"; -import { Task, TaskStatus } from "@lit/task"; -import { LitElement, css, html, nothing } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { - environmentContext, - type Environment, -} from "../../contexts/environment.js"; -import { InputEnterEvent } from "../../events/events.js"; -import { - fetchAvailableConnections, - type Connection, -} from "./connection-server.js"; -import "./connection-signin.js"; -import { - ExpiredTokenResult, - TokenVendor, - tokenVendorContext, -} from "./token-vendor.js"; - -/** - * Input element for handling secrets provided by OAuth connections. - */ -@customElement("bb-connection-input") -export class ConnectionInput extends LitElement { - @property() - connectionId?: string; - - @consume({ context: environmentContext }) - environment?: Environment; - - @consume({ context: tokenVendorContext }) - tokenVendor?: TokenVendor; - - #availableConnections = fetchAvailableConnections( - this, - () => this.environment, - // Don't autorun because we only need to do this fetch if we need to sign in - // from scratch. - false - ); - - #refreshTask = new Task(this, { - autoRun: false, - task: async ( - // TOOD(aomarks) The way we receive parameters here is a bit odd. It would - // be cool if I could have some parameters defined in `args`, and others - // passed to `run`, but right now Task only allows one or the other. - [expired]: [ExpiredTokenResult], - { signal } - ) => { - if (!expired) { - throw new Error("Uninitialized"); - } - const refreshed = await expired.refresh({ signal }); - this.#broadcastSecret( - refreshed.grant.access_token, - refreshed.grant.client_id - ); - }, - }); - - static styles = css` - bb-connection-signin { - margin-top: 14px; - } - `; - - render() { - if (!this.tokenVendor || !this.connectionId) { - return nothing; - } - const grant = this.tokenVendor.getToken(this.connectionId); - if (grant.state === "signedout") { - return this.#renderSigninButton(); - } else if (grant.state === "expired") { - return this.#refreshAndRenderStatus(grant); - } - this.#broadcastSecret(grant.grant.access_token, grant.grant.client_id); - return html`Token was fresh`; - } - - #renderSigninButton() { - if (!this.connectionId) { - return ""; - } - if (this.#availableConnections.status === TaskStatus.INITIAL) { - this.#availableConnections.run(); - } - return this.#availableConnections.render({ - pending: () => html`

    Loading connections ...

    `, - error: (e) => html`

    Error loading connections: ${e}

    `, - complete: (connections: Connection[]) => { - const connection = connections.find( - (connection) => connection.id === this.connectionId - ); - if (!connection) { - return html`

    - Could not find a connection for ${this.connectionId} -

    `; - } - return html` { - this.#broadcastSecret(token, connection.clientId); - }} - >`; - }, - }); - } - - #refreshAndRenderStatus(grant: ExpiredTokenResult) { - if (this.#refreshTask.status === TaskStatus.INITIAL) { - this.#refreshTask.run([grant]); - } - return this.#refreshTask.render({ - pending: () => html`

    Refreshing token ...

    `, - error: (e) => html`

    Error refreshing token: ${e}

    `, - complete: () => html`

    Token refreshed!

    `, - }); - } - - #broadcastSecret(secret: string, clientId: string) { - this.dispatchEvent( - new InputEnterEvent( - this.id, - { clientId, secret }, - // Disable allowSavingIfSecret so that it does not get saved to the - // regular secrets section, because we're managing this secret in a - // special way using the connections system. - false - ) - ); - } -} diff --git a/packages/shared-ui/src/elements/connection/connection-server.ts b/packages/shared-ui/src/elements/connection/connection-server.ts deleted file mode 100644 index d5785026cf1..00000000000 --- a/packages/shared-ui/src/elements/connection/connection-server.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Task } from "@lit/task"; -import type { ReactiveControllerHost } from "lit"; -import type { Environment } from "../../contexts/environment.js"; - -export function fetchAvailableConnections( - host: ReactiveControllerHost, - environment: () => Environment | undefined, - autoRun: boolean -): Task { - return new Task(host, { - autoRun, - args: () => [environment()?.connectionServerUrl], - task: async ([connectionServerUrl], { signal }) => { - if (!connectionServerUrl) { - return []; - } - const httpRes = await fetch(new URL("list", connectionServerUrl), { - signal, - credentials: "include", - }); - if (!httpRes.ok) { - throw new Error(String(httpRes.status)); - } - const jsonRes = (await httpRes.json()) as ListConnectionsResponse; - return jsonRes.connections; - }, - }); -} - -// IMPORTANT: Keep in sync with -// breadboard/packages/connection-server/src/api/list.ts -export interface ListConnectionsResponse { - connections: Connection[]; -} - -export interface Connection { - id: string; - clientId: string; - authUrl: string; - title: string; - description?: string; - icon?: string; -} diff --git a/packages/shared-ui/src/elements/connection/connection-settings.ts b/packages/shared-ui/src/elements/connection/connection-settings.ts deleted file mode 100644 index 7e51cca52f5..00000000000 --- a/packages/shared-ui/src/elements/connection/connection-settings.ts +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { consume } from "@lit/context"; -import { LitElement, css, html } from "lit"; -import { customElement } from "lit/decorators.js"; -import { - environmentContext, - type Environment, -} from "../../contexts/environment.js"; -import type { CustomSettingsElement } from "../../types/types.js"; -import { - fetchAvailableConnections, - type Connection, -} from "./connection-server.js"; -import "./connection-signin.js"; - -/** - * Custom settings panel for signing in and out of connections to third party - * apps/services. - */ -@customElement("bb-connection-settings") -export class ConnectionSettings - extends LitElement - implements CustomSettingsElement -{ - @consume({ context: environmentContext }) - environment?: Environment; - - /** - * The available connections vary across deployment environments, so we fetch - * them from the Breadboard Connection Server dynamically. - */ - #availableConnections = fetchAvailableConnections( - this, - () => this.environment, - /* autorun */ true - ); - - static styles = css` - ul { - margin: 8px 0 0 0; - padding: 0; - width: 100%; - } - li { - list-style-type: none; - margin-bottom: 15px; - } - `; - - render() { - const connectionServerUrl = this.environment?.connectionServerUrl; - if (!connectionServerUrl) { - return html`No connection server URL configured.`; - } - return this.#availableConnections.render({ - pending: () => html`

    Loading connections ...

    `, - error: (e) => html`

    Error loading connections: ${e}

    `, - complete: (connections: Connection[]) => { - if (connections.length === 0) { - return html`

    No connections available

    `; - } - return html`
      - ${connections.map( - (connection) => - html`
    • - -
    • ` - )} -
    `; - }, - }); - } -} diff --git a/packages/shared-ui/src/elements/connection/connection-signin.ts b/packages/shared-ui/src/elements/connection/connection-signin.ts deleted file mode 100644 index beef5e9ecbb..00000000000 --- a/packages/shared-ui/src/elements/connection/connection-signin.ts +++ /dev/null @@ -1,286 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { consume } from "@lit/context"; -import { LitElement, css, html, type PropertyValues } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import { - environmentContext, - type Environment, -} from "../../contexts/environment.js"; -import { settingsHelperContext } from "../../contexts/settings-helper.js"; -import { SETTINGS_TYPE, type SettingsHelper } from "../../types/types.js"; -import { - oauthTokenBroadcastChannelName, - type GrantResponse, - type TokenGrant, - type OAuthStateParameter, -} from "./connection-common.js"; -import type { Connection } from "./connection-server.js"; - -/** - * Widget for signing in and out of a connection to a third party app/service. - */ -@customElement("bb-connection-signin") -export class ConnectionSignin extends LitElement { - @property({ attribute: false }) - connection?: Connection; - - @consume({ context: environmentContext }) - environment?: Environment; - - @consume({ context: settingsHelperContext }) - settingsHelper?: SettingsHelper; - - @state() - private _nonce = crypto.randomUUID(); - - @state() - private _state: "signedout" | "pending" | "signedin" = "signedout"; - - static styles = css` - :host { - display: grid; - grid-template-columns: max-content 1fr max-content; - column-gap: 10px; - } - - .icon { - width: 20px; - height: 20px; - } - .icon.missing { - background: var(--bb-icon-lan) center center / 20px 20px no-repeat; - } - - .title { - font-size: var(--bb-body-medium); - font-weight: normal; - margin: 0; - } - .description { - font-size: var(--bb-body-x-small); - line-height: var(--bb-body-line-height-x-small); - margin: 0; - } - - .signin, - .pending, - .signout { - display: flex; - align-items: center; - justify-content: center; - height: 19px; - font-size: 13px; - border-radius: 9px; - padding: 1px 8px; - } - - .signin { - background: var(--bb-ui-100); - color: var(--bb-ui-700); - text-decoration: none; - } - .signin:hover { - background: var(--bb-ui-200); - color: var(--bb-ui-800); - } - - .pending { - background: var(--bb-ui-100); - color: var(--bb-ui-700); - opacity: 50%; - pointer-events: none; - } - - .signout { - background: var(--bb-neutral-200); - color: var(--bb-neutral-600); - cursor: pointer; - border: none; - height: 21px; - } - .signout:hover { - background: var(--bb-neutral-300); - color: var(--bb-neutral-700); - } - `; - - override updated(changes: PropertyValues) { - if ( - (changes.has("connection") || changes.has("settingsHelper")) && - this.connection && - this.settingsHelper && - this._state !== "pending" - ) { - const setting = this.settingsHelper.get( - SETTINGS_TYPE.CONNECTIONS, - this.connection.id - ); - this._state = setting === undefined ? "signedout" : "signedin"; - } - } - - override render() { - if (!this.connection) { - return ""; - } - - const icon = this.connection.icon - ? html`` - : html``; - - const metadata = html`
    -

    ${this.connection.title}

    -

    ${this.connection.description}

    -
    `; - - return html`${icon} ${metadata} ${this.#renderButton()}`; - } - - #renderButton() { - if (!this.connection || !this.settingsHelper) { - return ""; - } - - switch (this._state) { - case "signedout": { - return html``; - } - case "pending": { - return html``; - } - case "signedin": { - return html``; - } - } - this._state satisfies never; - } - - #updatedAuthUrl(): string { - if (!this.connection) { - return ""; - } - let redirectUri = this.environment?.connectionRedirectUrl; - if (!redirectUri) { - return ""; - } - // Resolve it since environment.connectionRedirectUrl is likely relative - // (but resolve it using the origin, not the full current url, because it's - // a global setting). - redirectUri = new URL(redirectUri, new URL(window.location.href).origin) - .href; - const authUrl = new URL(this.connection.authUrl); - authUrl.searchParams.set("redirect_uri", redirectUri); - authUrl.searchParams.set( - "state", - JSON.stringify({ - connectionId: this.connection.id, - nonce: this._nonce, - } satisfies OAuthStateParameter) - ); - return authUrl.href; - } - - async #onClickSignin() { - const now = Date.now(); - if (!this.connection || !this.settingsHelper) { - return; - } - this._state = "pending"; - const nonce = this._nonce; - // Reset the nonce in case the user signs out and signs back in again, since - // we don't want to ever mix up different requests. - setTimeout( - // TODO(aomarks) This shouldn't be necessary, what's up? - () => (this._nonce = crypto.randomUUID()), - 500 - ); - // The OAuth broker page will know to broadcast the token on this unique - // channel because it also knows the nonce (since we pack that in the OAuth - // "state" parameter). - const channelName = oauthTokenBroadcastChannelName(nonce); - const channel = new BroadcastChannel(channelName); - const grantResponse = await new Promise((resolve) => { - channel.addEventListener("message", (m) => resolve(m.data), { - once: true, - }); - }); - channel.close(); - if (grantResponse.error !== undefined) { - // TODO(aomarks) Show error info in the UI. - console.error(grantResponse.error); - this._state = "signedout"; - return; - } - const settingsValue: TokenGrant = { - client_id: this.connection.clientId, - access_token: grantResponse.access_token, - expires_in: grantResponse.expires_in, - refresh_token: grantResponse.refresh_token, - issue_time: now, - }; - await this.settingsHelper.set( - SETTINGS_TYPE.CONNECTIONS, - this.connection.id, - { - name: this.connection.id, - value: JSON.stringify(settingsValue), - } - ); - this.dispatchEvent(new TokenGrantedEvent(grantResponse.access_token)); - this._state = "signedin"; - } - - async #onClickSignout() { - if (!this.settingsHelper || !this.connection) { - return; - } - await this.settingsHelper.delete( - SETTINGS_TYPE.CONNECTIONS, - this.connection.id - ); - this._state = "signedout"; - } -} - -class TokenGrantedEvent extends Event { - static eventName = "bbtokengranted" as const; - readonly token: string; - constructor(token: string) { - super(TokenGrantedEvent.eventName); - this.token = token; - } -} - -declare global { - interface HTMLElementEventMap { - [TokenGrantedEvent.eventName]: TokenGrantedEvent; - } -} diff --git a/packages/shared-ui/src/elements/connection/token-vendor.ts b/packages/shared-ui/src/elements/connection/token-vendor.ts deleted file mode 100644 index 3ff7753be01..00000000000 --- a/packages/shared-ui/src/elements/connection/token-vendor.ts +++ /dev/null @@ -1,196 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { createContext } from "@lit/context"; -import { type Environment } from "../../contexts/environment.js"; -import { SETTINGS_TYPE, type SettingsHelper } from "../../types/types.js"; -import { - type RefreshRequest, - type RefreshResponse, - type TokenGrant, -} from "./connection-common.js"; -import { type ListConnectionsResponse } from "./connection-server.js"; - -export const tokenVendorContext = createContext("TokenVendor"); - -export type TokenResult = - | ValidTokenResult - | ExpiredTokenResult - | SignedOutTokenResult; - -/** - * The token is valid and ready to be used. - */ -export interface ValidTokenResult { - state: "valid"; - grant: TokenGrant; - expired?: never; - refresh?: never; -} - -/** - * The user is signed-in to this service, but the token we have is expired. Call - * the `refresh` method to automatically refresh it. - */ -export interface ExpiredTokenResult { - state: "expired"; - grant?: never; - expired?: never; - refresh: (opts?: { signal?: AbortSignal }) => Promise; -} - -/** - * The user is not signed-in to this service. In this case, typically a - * `` element should be displayed to prompt the user to - * sign-in. - */ -export interface SignedOutTokenResult { - state: "signedout"; - grant?: never; - expired?: never; - refresh?: never; -} - -/** - * If a token is going to expire in less than this many milliseconds, we treat - * it as though it is already expired, since there might be a delay between - * returning it from here and it actually getting used. - */ -const EXPIRY_THRESHOLD_MS = /* 1 minute */ 60_000; - -/** - * Provides access to authorization tokens stored in settings, and the ability - * to refresh them if they are expired. - * - * There should typically be one instance of this class per Visual Editor, and - * elements should discover it using the {@link tokenVendorContext} Lit - * context, which should be provided by the top-level Visual Editor element. - */ -export class TokenVendor { - #settings: SettingsHelper; - #environment: Environment; - - constructor(settings: SettingsHelper, environment: Environment) { - this.#settings = settings; - this.#environment = environment; - } - - getToken(connectionId: string): TokenResult { - const grantJsonText = this.#settings.get( - SETTINGS_TYPE.CONNECTIONS, - connectionId - ); - if (grantJsonText === undefined) { - return { state: "signedout" }; - } - const grant = JSON.parse(String(grantJsonText.value)) as TokenGrant; - const needsClientIdRepair = grant.client_id === undefined; - if (grantIsExpired(grant) || needsClientIdRepair) { - return { - state: "expired", - refresh: (opts?: { signal?: AbortSignal }) => - this.#refresh(connectionId, grant, opts?.signal), - }; - } - return { state: "valid", grant }; - } - - async #refresh( - connectionId: string, - expiredGrant: TokenGrant, - signal?: AbortSignal - ): Promise { - if (expiredGrant.client_id === undefined) { - // We used to not store the client_id locally, but later discovered it's - // helpful to store because it's needed for some APIs. - expiredGrant = await this.#repairGrantWithMissingClientId( - connectionId, - expiredGrant - ); - } - - const refreshUrl = new URL( - "refresh", - this.#environment.connectionServerUrl - ); - refreshUrl.search = new URLSearchParams({ - connection_id: connectionId, - refresh_token: expiredGrant.refresh_token, - } satisfies RefreshRequest).toString(); - - const now = Date.now(); - const httpRes = await fetch(refreshUrl, { - signal, - credentials: "include", - }); - if (!httpRes.ok) { - throw new Error(String(httpRes.status)); - } - const jsonRes = (await httpRes.json()) as RefreshResponse; - if (jsonRes.error !== undefined) { - throw new Error(jsonRes.error); - } - - const updatedGrant: TokenGrant = { - client_id: expiredGrant.client_id, - access_token: jsonRes.access_token, - expires_in: jsonRes.expires_in, - issue_time: now, - refresh_token: expiredGrant.refresh_token, - }; - await this.#settings.set(SETTINGS_TYPE.CONNECTIONS, connectionId, { - name: connectionId, - value: JSON.stringify(updatedGrant), - }); - return { state: "valid", grant: updatedGrant }; - } - - async #repairGrantWithMissingClientId( - connectionId: string, - grant: TokenGrant - ): Promise { - const httpRes = await fetch( - new URL("list", this.#environment.connectionServerUrl), - { credentials: "include" } - ); - if (!httpRes.ok) { - throw new Error( - `HTTP ${httpRes.status} error calling list connections API ` + - `while repairing a grant with missing client id.` - ); - } - let jsonRes: ListConnectionsResponse; - try { - jsonRes = await httpRes.json(); - } catch { - throw new Error( - `Error decoding JSON from list connections API ` + - `while repairing a grant with missing client id.` - ); - } - for (const connection of jsonRes.connections) { - if (connection.id === connectionId) { - return { - ...grant, - client_id: connection.clientId, - }; - } - } - throw new Error( - `Could not find a connection with id ` + - `"${connectionId}" from list connections API ` + - `while repairing a grant with missing client id.` - ); - } -} - -function grantIsExpired(grant: TokenGrant): boolean { - const expiresAt = - /* absolute milliseconds */ grant.issue_time + - /* relative seconds */ grant.expires_in * 1000; - const expiresIn = expiresAt - /* unix milliseconds */ Date.now(); - return expiresIn <= EXPIRY_THRESHOLD_MS; -} diff --git a/packages/shared-ui/src/elements/editor/editor.ts b/packages/shared-ui/src/elements/editor/editor.ts deleted file mode 100644 index d7c4c86193f..00000000000 --- a/packages/shared-ui/src/elements/editor/editor.ts +++ /dev/null @@ -1,2353 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - CommentNode, - Edge, - EditSpec, - GraphDescriptor, - GraphProviderCapabilities, - GraphProviderExtendedCapabilities, - InspectableGraph, - InspectableNodePorts, - InspectableRun, - NodeConfiguration, - NodeDescriptor, - NodeHandlerMetadata, - NodeValue, - SubGraphs, -} from "@google-labs/breadboard"; -import { - HTMLTemplateResult, - LitElement, - PropertyValues, - css, - html, - nothing, -} from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import { map } from "lit/directives/map.js"; -import { Ref, createRef, ref } from "lit/directives/ref.js"; -import { until } from "lit/directives/until.js"; -import { MAIN_BOARD_ID } from "../../constants/constants.js"; -import { - CommentEditRequestEvent, - EdgeChangeEvent, - EdgeValueSelectedEvent, - GraphCommentEditRequestEvent, - GraphEdgeAttachEvent, - GraphEdgeDetachEvent, - GraphEdgeValueSelectedEvent, - GraphEntityRemoveEvent, - GraphHideTooltipEvent, - GraphInitialDrawEvent, - GraphInteractionEvent, - GraphNodeActivitySelectedEvent, - GraphNodeDeleteEvent, - GraphNodeEdgeChangeEvent, - GraphNodeEditEvent, - GraphNodesVisualUpdateEvent, - GraphShowTooltipEvent, - HideTooltipEvent, - KitNodeChosenEvent, - MultiEditEvent, - NodeActivitySelectedEvent, - NodeConfigurationUpdateRequestEvent, - NodeCreateEvent, - NodeDeleteEvent, - NodeTypeRetrievalErrorEvent, - RedoEvent, - RunEvent, - SaveAsEvent, - SaveEvent, - ShowTooltipEvent, - StopEvent, - SubGraphChosenEvent, - SubGraphCreateEvent, - SubGraphDeleteEvent, - ToggleBoardActivityEvent, - UndoEvent, -} from "../../events/events.js"; -import { GraphEdge } from "./graph-edge.js"; -import { GraphRenderer } from "./graph-renderer.js"; -import type { NodeSelector } from "./node-selector.js"; -import { edgeToString } from "./utils.js"; - -const ZOOM_KEY = "bb-editor-zoom-to-highlighted-node-during-runs"; -const DATA_TYPE = "text/plain"; -const PASTE_OFFSET = 50; - -import { TopGraphRunResult } from "../../types/types.js"; -import { GraphAssets } from "./graph-assets.js"; -import { classMap } from "lit/directives/class-map.js"; - -function getDefaultConfiguration(type: string): NodeConfiguration | undefined { - if (type !== "input" && type !== "output") { - return undefined; - } - - return { - schema: { - properties: { - context: { - type: "array", - title: "Context", - items: { - type: "object", - examples: [], - behavior: ["llm-content"], - default: - type === "input" - ? '{"role":"user","parts":[{"text":""}]}' - : "null", - }, - }, - }, - type: "object", - required: [], - }, - }; -} - -type EditedNode = { - editAction: "add" | "update"; - id: string; -}; - -@customElement("bb-editor") -export class Editor extends LitElement { - @property() - graph: InspectableGraph | null = null; - - @property() - subGraphId: string | null = null; - - @property() - run: InspectableRun | null = null; - - @property() - boardId: number = -1; - - @property() - capabilities: false | GraphProviderCapabilities = false; - - @property() - extendedCapabilities: false | GraphProviderExtendedCapabilities = false; - - @property() - canUndo = false; - - @property() - canRedo = false; - - @property() - collapseNodesByDefault = false; - - @property() - hideSubboardSelectorWhenEmpty = false; - - @property() - showNodeShortcuts = true; - - @property() - topGraphResult: TopGraphRunResult | null = null; - - @state() - nodeValueBeingEdited: EditedNode | null = null; - - @state() - defaultConfiguration: NodeConfiguration | null = null; - - @property({ reflect: true }) - invertZoomScrollDirection = false; - - @property() - showNodeTypeDescriptions = true; - - @property() - showNodePreviewValues = true; - - @property() - assetPrefix = ""; - - @property() - showControls = true; - - @property() - readOnly = false; - - @property() - showReadOnlyOverlay = false; - - @property() - highlightInvalidWires = false; - - @property() - showExperimentalComponents = false; - - @property() - zoomToHighlightedNodeDuringRuns = false; - - @property() - set showPortTooltips(value: boolean) { - this.#graphRenderer.showPortTooltips = value; - } - - get showPortTooltips() { - return this.#graphRenderer.showPortTooltips; - } - - @state() - showOverflowMenu = false; - - #graphRenderer = new GraphRenderer(); - // Incremented each time a graph is updated, used to avoid extra work - // inspecting ports when the graph is updated. - #graphVersion = 0; - #lastBoardId: number = -1; - #lastSubGraphId: string | null = null; - - #onKeyDownBound = this.#onKeyDown.bind(this); - #onDropBound = this.#onDrop.bind(this); - #onDragOverBound = this.#onDragOver.bind(this); - #onResizeBound = this.#onResize.bind(this); - #onPointerMoveBound = this.#onPointerMove.bind(this); - #onPointerDownBound = this.#onPointerDown.bind(this); - #onGraphNodesVisualUpdateBound = this.#onGraphNodesVisualUpdate.bind(this); - #onGraphEdgeAttachBound = this.#onGraphEdgeAttach.bind(this); - #onGraphEdgeDetachBound = this.#onGraphEdgeDetach.bind(this); - #onGraphEdgeChangeBound = this.#onGraphEdgeChange.bind(this); - #onGraphNodeDeleteBound = this.#onGraphNodeDelete.bind(this); - #onGraphEntityRemoveBound = this.#onGraphEntityRemove.bind(this); - #onGraphNodeEditBound = this.#onGraphNodeEdit.bind(this); - #onGraphEdgeValueSelectedBound = this.#onGraphEdgeValueSelected.bind(this); - #onGraphNodeActivitySelectedBound = - this.#onGraphNodeActivitySelected.bind(this); - #onGraphInteractionBound = this.#onGraphInteraction.bind(this); - #onGraphShowTooltipBound = this.#onGraphShowTooltip.bind(this); - #onGraphHideTooltipBound = this.#onGraphHideTooltip.bind(this); - #onGraphCommentEditRequestBound = this.#onGraphCommentEditRequest.bind(this); - - #top = 0; - #left = 0; - #addButtonRef: Ref = createRef(); - #nodeSelectorRef: Ref = createRef(); - #activityMarkerRef: Ref = createRef(); - - #writingToClipboard = false; - #readingFromClipboard = false; - #lastX = 0; - #lastY = 0; - #pasteCount = 0; - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: flex; - align-items: center; - justify-content: center; - background-color: var(--bb-ui-50); - overflow: auto; - position: relative; - user-select: none; - pointer-events: auto; - width: 100%; - height: 100%; - position: relative; - } - - bb-node-selector { - visibility: hidden; - pointer-events: none; - position: absolute; - bottom: var(--bb-grid-size-12); - left: 0; - } - - #nodes { - height: calc(var(--bb-grid-size) * 9); - position: absolute; - bottom: calc(var(--bb-grid-size) * 3); - left: calc(var(--bb-grid-size) * 3); - border-radius: 50px; - border: 1px solid #d9d9d9; - background: #ffffff; - display: flex; - align-items: center; - justify-content: center; - padding: 0 var(--bb-grid-size) 0 var(--bb-grid-size-3); - } - - #shortcut-add-comment, - #shortcut-add-specialist, - #shortcut-add-human, - #shortcut-add-looper { - font-size: 0; - width: 20px; - height: 20px; - background: var(--bb-neutral-0); - margin-right: calc(var(--bb-grid-size) * 2); - border: none; - cursor: grab; - } - - #shortcut-add-specialist { - background: var(--bb-neutral-0) var(--bb-icon-smart-toy) center center / - 20px 20px no-repeat; - } - - #shortcut-add-human { - background: var(--bb-neutral-0) var(--bb-icon-human) center center / 20px - 20px no-repeat; - } - - #shortcut-add-looper { - background: var(--bb-neutral-0) var(--bb-icon-laps) center center / 20px - 20px no-repeat; - } - - #shortcut-add-comment { - background: var(--bb-neutral-0) var(--bb-icon-edit) center center / 20px - 20px no-repeat; - } - - #shortcut-add-specialist:active, - #shortcut-add-human:active, - #shortcut-add-looper:active { - cursor: grabbing; - } - - label[for="add-node"] { - font-size: 0; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - } - - label[for="add-node"]::before { - content: ""; - width: 24px; - height: 24px; - background: var(--bb-ui-100) var(--bb-icon-more-vert) center center / 20px - 20px no-repeat; - border-radius: 50%; - transition: opacity 0.3s cubic-bezier(0, 0, 0.3, 1); - opacity: 0.5; - } - - label[for="add-node"]:hover::before { - opacity: 1; - } - - #add-node { - display: none; - } - - #add-node:checked ~ bb-node-selector { - visibility: visible; - pointer-events: auto; - } - - #add-node:checked ~ label[for="add-node"] { - opacity: 1; - } - - bb-graph-renderer { - display: block; - width: 100%; - height: 100%; - outline: none; - overflow: hidden; - } - - #controls { - height: var(--bb-grid-size-9); - position: absolute; - top: var(--bb-grid-size-3); - left: var(--bb-grid-size-3); - background: #fff; - border-radius: 40px; - padding: 0 var(--bb-grid-size) 0 var(--bb-grid-size-3); - - border: 1px solid var(--bb-neutral-300); - display: flex; - align-items: center; - } - - #controls button { - margin-left: calc(var(--bb-grid-size) * 2); - } - - #controls button:first-of-type, - #controls .divider + button { - margin-left: 0; - } - - #debug { - width: 140px; - - height: calc(var(--bb-grid-size) * 9); - position: absolute; - bottom: calc(var(--bb-grid-size) * 3); - right: calc(var(--bb-grid-size) * 2); - - background: var(--bb-ui-600) var(--bb-icon-debug-inverted) 12px center / - 20px 20px no-repeat; - color: #fff; - border-radius: 20px; - border: none; - font-size: var(--bb-label-large); - padding: var(--bb-grid-size-2) var(--bb-grid-size-5) var(--bb-grid-size-2) - var(--bb-grid-size-9); - margin-right: var(--bb-grid-size-2); - cursor: pointer; - opacity: 0.8; - transition: opacity 0.3s cubic-bezier(0, 0, 0.3, 1); - } - - #debug:hover, - #debug:focus { - opacity: 1; - } - - #debug[disabled] { - opacity: 0.4; - cursor: auto; - } - - #reset-layout, - #zoom-to-fit, - #undo, - #redo, - #save-board, - #overflow { - width: 20px; - height: 20px; - background: center center no-repeat; - background-size: 20px 20px; - font-size: 0; - transition: opacity 0.3s cubic-bezier(0, 0, 0.3, 1); - opacity: 0.5; - border: none; - } - - #overflow { - border-radius: 50%; - width: 24px; - height: 24px; - } - - #reset-layout[disabled], - #zoom-to-fit[disabled], - #undo[disabled], - #redo[disabled], - #save-board[disabled], - #overflow[disabled] { - opacity: 0.45; - } - - #reset-layout { - background-image: var(--bb-icon-reset-nodes); - } - - #zoom-to-fit { - background-image: var(--bb-icon-fit); - } - - #undo { - margin: 0; - background-image: var(--bb-icon-undo); - } - - #redo { - background-image: var(--bb-icon-redo); - } - - #save-board { - background-image: var(--bb-icon-save); - } - - #overflow { - background: var(--bb-ui-100) var(--bb-icon-more-vert) center center / 20px - 20px no-repeat; - } - - #reset-layout:not([disabled]):hover, - #zoom-to-fit:not([disabled]):hover, - #undo:not([disabled]):hover, - #redo:not([disabled]):hover, - #save-board:not([disabled]):hover, - #overflow:not([disabled]):hover, - #reset-layout:not([disabled]):focus, - #zoom-to-fit:not([disabled]):focus, - #undo:not([disabled]):focus, - #redo:not([disabled]):focus, - #save-board:not([disabled]):focus, - #overflow:not([disabled]):focus { - transition-duration: 0.1s; - opacity: 1; - cursor: pointer; - } - - .divider { - width: 1px; - height: calc(var(--bb-grid-size) * 5); - background: var(--bb-neutral-300); - margin: 0px calc(var(--bb-grid-size) * 3); - } - - bb-overflow-menu { - position: absolute; - top: calc(var(--bb-grid-size) * 11); - right: auto; - left: calc(var(--bb-grid-size) * 40); - } - - #subgraph-selector { - color: var(--bb-ui-500); - border: none; - font-size: var(--bb-label-large); - } - - #add-sub-board, - #delete-sub-board { - background: none; - width: 16px; - height: 16px; - background-position: center center; - background-repeat: no-repeat; - background-size: 16px 16px; - border: none; - font-size: 0; - opacity: 0.5; - cursor: pointer; - } - - #add-sub-board { - background-image: var(--bb-icon-add-circle); - } - - #delete-sub-board { - background-image: var(--bb-icon-delete); - } - - #add-sub-board:hover, - #delete-sub-board:hover { - opacity: 1; - } - - #delete-sub-board[disabled] { - opacity: 0.3; - cursor: auto; - } - - #readonly-overlay { - display: flex; - align-items: center; - height: var(--bb-grid-size-9); - position: absolute; - top: var(--bb-grid-size-3); - left: 50%; - transform: translateX(-50%); - color: var(--bb-boards-900); - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - background: var(--bb-boards-300); - border-radius: var(--bb-grid-size-10); - padding: 0 var(--bb-grid-size-4) 0 var(--bb-grid-size-3); - } - - #readonly-overlay::before { - content: ""; - width: 20px; - height: 20px; - background: var(--bb-icon-saved-readonly) center center / 20px 20px - no-repeat; - margin-right: var(--bb-grid-size); - mix-blend-mode: difference; - } - - #activity-marker { - align-items: center; - background: var(--bb-neutral-50); - border-radius: var(--bb-grid-size-10); - border: 1px solid var(--bb-neutral-300); - bottom: calc(var(--bb-grid-size) * 3); - color: var(--bb-neutral-900); - cursor: pointer; - display: flex; - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - height: var(--bb-grid-size-9); - justify-content: center; - position: absolute; - right: calc(var(--bb-grid-size) * 42); - transition: all 0.3s cubic-bezier(0, 0, 0.3, 1); - width: var(--bb-grid-size-9); - } - - #activity-marker::after { - content: ""; - width: 100%; - height: 100%; - pointer-events: none; - opacity: 0.4; - top: -8px; - left: -8px; - border-radius: 50%; - position: absolute; - } - - #activity-marker.pending { - border: 1px solid var(--bb-inputs-700); - background: var(--bb-inputs-500); - color: var(--bb-neutral-0); - } - - #activity-marker.pending::after { - animation: expand 3s cubic-bezier(0, 0, 0.3, 1) forwards infinite; - } - - #activity-marker.error { - border: 1px solid var(--bb-warning-700); - background: var(--bb-warning-600); - color: var(--bb-neutral-0); - } - - @keyframes expand { - 0% { - opacity: 0; - transform: scale(1); - border: 8px solid var(--bb-inputs-500); - } - - 5% { - opacity: 0.4; - } - - 50% { - opacity: 0; - transform: scale(1.5) translate(4px, 4px); - } - - 100% { - opacity: 0; - transform: scale(1.5) translate(4px, 4px); - border: 0px solid var(--bb-inputs-500); - } - } - - #active-component { - position: absolute; - bottom: calc(var(--bb-grid-size) * 3); - right: calc(var(--bb-grid-size) * 54); - border-radius: 50px; - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - border: none; - padding: 0 var(--bb-grid-size-4) 0 var(--bb-grid-size-2); - display: flex; - align-items: center; - background: var(--bb-neutral-0); - border-radius: var(--bb-grid-size-10); - height: var(--bb-grid-size-9); - cursor: pointer; - color: var(--bb-neutral-500); - border: 1px solid var(--bb-neutral-300); - transition: all 0.3s cubic-bezier(0, 0, 0.3, 1); - } - - #controls #active-component { - margin-left: 0; - } - - #active-component:hover { - color: var(--bb-inputs-600); - border: 1px solid var(--bb-inputs-300); - } - - #active-component::before { - content: ""; - width: 20px; - height: 20px; - padding-right: var(--bb-grid-size); - background: var(--bb-icon-directions) left center / 20px 20px no-repeat; - } - - #active-component.active { - opacity: 1; - color: var(--bb-inputs-700); - background: var(--bb-inputs-50); - border: 1px solid var(--bb-inputs-500); - } - - #active-component:hover::before, - #active-component.active::before { - background: var(--bb-icon-directions-active) left center / 20px 20px - no-repeat; - } - `; - - async #processGraph(): Promise { - if (GraphAssets.assetPrefix !== this.assetPrefix) { - GraphAssets.instance().loadAssets(this.assetPrefix); - await GraphAssets.instance().loaded; - } - - await this.#graphRenderer.ready; - - if (!this.graph) { - this.#graphRenderer.deleteGraphs(); - return this.#graphRenderer; - } - - this.#graphVersion++; - this.#graphRenderer.readOnly = this.readOnly; - this.#graphRenderer.highlightInvalidWires = this.highlightInvalidWires; - - let selectedGraph = this.graph; - if (this.subGraphId) { - const subgraphs = selectedGraph.graphs(); - if (subgraphs[this.subGraphId]) { - selectedGraph = subgraphs[this.subGraphId]; - } else { - console.warn(`Unable to locate subgraph by name: ${this.subGraphId}`); - } - } - - // Force a reset when the board changes. - if (this.boardId !== this.#lastBoardId) { - this.#graphRenderer.removeAllGraphs(); - this.#lastBoardId = this.boardId; - } - - const ports = new Map(); - const typeMetadata = new Map(); - const graphVersion = this.#graphVersion; - - for (const node of selectedGraph.nodes()) { - ports.set(node.descriptor.id, await node.ports()); - try { - typeMetadata.set(node.descriptor.type, await node.type().metadata()); - } catch (err) { - // In the event of failing to get the type info, suggest removing the - // node from the graph. - this.dispatchEvent( - new NodeTypeRetrievalErrorEvent(node.descriptor.id, this.subGraphId) - ); - } - - if (this.#graphVersion !== graphVersion) { - // Another update has come in, bail out. - return this.#graphRenderer; - } - } - - if (!this.graph) { - return this.#graphRenderer; - } - - const url = this.graph.raw().url || ""; - this.#graphRenderer.hideAllGraphs(); - - // Attempt to update the graph if it already exists. - const updated = this.#graphRenderer.updateGraphByUrl(url, this.subGraphId, { - showNodeTypeDescriptions: this.showNodeTypeDescriptions, - showNodePreviewValues: this.showNodePreviewValues, - collapseNodesByDefault: this.collapseNodesByDefault, - ports: ports, - typeMetadata, - edges: selectedGraph.edges(), - nodes: selectedGraph.nodes(), - metadata: selectedGraph.metadata(), - }); - - if (updated) { - this.#graphRenderer.showGraph(url, this.subGraphId); - if (this.topGraphResult) { - this.#graphRenderer.topGraphResult = this.topGraphResult; - } - - return this.#graphRenderer; - } - - if (this.#lastSubGraphId !== this.subGraphId) { - // TODO: Need to figure out how to encode the subgraph/node id combo. - this.#graphRenderer.topGraphResult = null; - } - - this.#graphRenderer.createGraph({ - url, - subGraphId: this.subGraphId, - showNodeTypeDescriptions: this.showNodeTypeDescriptions, - showNodePreviewValues: this.showNodePreviewValues, - collapseNodesByDefault: this.collapseNodesByDefault, - ports: ports, - typeMetadata, - edges: selectedGraph.edges(), - nodes: selectedGraph.nodes(), - metadata: selectedGraph.metadata() || {}, - visible: false, - }); - - this.#graphRenderer.addEventListener( - GraphInitialDrawEvent.eventName, - () => { - this.#graphRenderer.showGraph(url, this.subGraphId); - this.#graphRenderer.zoomToFit(); - - // When we're loading a graph from existing results, we need to - // set the topGraphResult again so that it is applied to the newly - // created graph. - if (this.topGraphResult) { - this.#graphRenderer.topGraphResult = this.topGraphResult; - } - }, - { once: true } - ); - - return this.#graphRenderer; - } - - constructor() { - super(); - - this.zoomToHighlightedNodeDuringRuns = - (globalThis.localStorage.getItem(ZOOM_KEY) ?? "true") === "true"; - } - - connectedCallback(): void { - super.connectedCallback(); - - this.#graphRenderer.addEventListener( - GraphEdgeAttachEvent.eventName, - this.#onGraphEdgeAttachBound - ); - - this.#graphRenderer.addEventListener( - GraphEdgeDetachEvent.eventName, - this.#onGraphEdgeDetachBound - ); - - this.#graphRenderer.addEventListener( - GraphNodeEdgeChangeEvent.eventName, - this.#onGraphEdgeChangeBound - ); - - this.#graphRenderer.addEventListener( - GraphNodeDeleteEvent.eventName, - this.#onGraphNodeDeleteBound - ); - - this.#graphRenderer.addEventListener( - GraphNodesVisualUpdateEvent.eventName, - this.#onGraphNodesVisualUpdateBound - ); - - this.#graphRenderer.addEventListener( - GraphEntityRemoveEvent.eventName, - this.#onGraphEntityRemoveBound - ); - - this.#graphRenderer.addEventListener( - GraphNodeEditEvent.eventName, - this.#onGraphNodeEditBound - ); - - this.#graphRenderer.addEventListener( - GraphEdgeValueSelectedEvent.eventName, - this.#onGraphEdgeValueSelectedBound - ); - - this.#graphRenderer.addEventListener( - GraphNodeActivitySelectedEvent.eventName, - this.#onGraphNodeActivitySelectedBound - ); - - this.#graphRenderer.addEventListener( - GraphInteractionEvent.eventName, - this.#onGraphInteractionBound - ); - - this.#graphRenderer.addEventListener( - GraphShowTooltipEvent.eventName, - this.#onGraphShowTooltipBound - ); - - this.#graphRenderer.addEventListener( - GraphHideTooltipEvent.eventName, - this.#onGraphHideTooltipBound - ); - - this.#graphRenderer.addEventListener( - GraphCommentEditRequestEvent.eventName, - this.#onGraphCommentEditRequestBound - ); - - window.addEventListener("resize", this.#onResizeBound); - this.addEventListener("keydown", this.#onKeyDownBound); - this.addEventListener("pointermove", this.#onPointerMoveBound); - this.addEventListener("pointerdown", this.#onPointerDownBound); - this.addEventListener("dragover", this.#onDragOverBound); - this.addEventListener("drop", this.#onDropBound); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - - this.#graphRenderer.removeEventListener( - GraphEdgeAttachEvent.eventName, - this.#onGraphEdgeAttachBound - ); - - this.#graphRenderer.removeEventListener( - GraphEdgeDetachEvent.eventName, - this.#onGraphEdgeDetachBound - ); - - this.#graphRenderer.removeEventListener( - GraphNodeEdgeChangeEvent.eventName, - this.#onGraphEdgeChangeBound - ); - - this.#graphRenderer.removeEventListener( - GraphNodeDeleteEvent.eventName, - this.#onGraphNodeDeleteBound - ); - - this.#graphRenderer.removeEventListener( - GraphNodesVisualUpdateEvent.eventName, - this.#onGraphNodesVisualUpdateBound - ); - - this.#graphRenderer.removeEventListener( - GraphEntityRemoveEvent.eventName, - this.#onGraphEntityRemoveBound - ); - - this.#graphRenderer.removeEventListener( - GraphNodeEditEvent.eventName, - this.#onGraphNodeEditBound - ); - - this.#graphRenderer.removeEventListener( - GraphEdgeValueSelectedEvent.eventName, - this.#onGraphEdgeValueSelectedBound - ); - - this.#graphRenderer.removeEventListener( - GraphNodeActivitySelectedEvent.eventName, - this.#onGraphNodeActivitySelectedBound - ); - - this.#graphRenderer.removeEventListener( - GraphInteractionEvent.eventName, - this.#onGraphInteractionBound - ); - - this.#graphRenderer.removeEventListener( - GraphShowTooltipEvent.eventName, - this.#onGraphShowTooltipBound - ); - - this.#graphRenderer.removeEventListener( - GraphHideTooltipEvent.eventName, - this.#onGraphHideTooltipBound - ); - - this.#graphRenderer.removeEventListener( - GraphCommentEditRequestEvent.eventName, - this.#onGraphCommentEditRequestBound - ); - - window.removeEventListener("resize", this.#onResizeBound); - this.removeEventListener("keydown", this.#onKeyDownBound); - this.removeEventListener("pointermove", this.#onPointerMoveBound); - this.removeEventListener("pointerdown", this.#onPointerDownBound); - this.removeEventListener("dragover", this.#onDragOverBound); - this.removeEventListener("drop", this.#onDropBound); - } - - protected willUpdate(changedProperties: PropertyValues): void { - if (!changedProperties.has("run")) { - return; - } - - this.#graphRenderer.zoomToHighlightedNode = - this.zoomToHighlightedNodeDuringRuns; - } - - #onGraphInteraction() { - // Only switch off the flag if there is a run active. - if (!this.topGraphResult?.currentNode) { - return; - } - - this.zoomToHighlightedNodeDuringRuns = false; - } - - #onGraphShowTooltip(evt: Event) { - const tooltipEvt = evt as GraphShowTooltipEvent; - this.dispatchEvent( - new ShowTooltipEvent(tooltipEvt.message, tooltipEvt.x, tooltipEvt.y) - ); - } - - #onGraphHideTooltip() { - this.dispatchEvent(new HideTooltipEvent()); - } - - #onGraphCommentEditRequest(evt: Event) { - const commentEvt = evt as GraphCommentEditRequestEvent; - this.dispatchEvent( - new CommentEditRequestEvent( - commentEvt.id, - commentEvt.x, - commentEvt.y, - this.subGraphId - ) - ); - } - - #onPointerMove(evt: PointerEvent) { - this.#lastX = evt.pageX - this.#left + window.scrollX; - this.#lastY = evt.pageY - this.#top - window.scrollY; - } - - #isNodeDescriptor(item: unknown): item is NodeDescriptor { - return ( - typeof item === "object" && - item !== null && - "id" in item && - "type" in item - ); - } - - #isEdge(item: unknown): item is Edge { - return ( - typeof item === "object" && - item !== null && - "from" in item && - "to" in item - ); - } - - async #onKeyDown(evt: KeyboardEvent) { - if (this.readOnly) { - return; - } - - const isMac = navigator.platform.indexOf("Mac") === 0; - const isCtrlCommand = isMac ? evt.metaKey : evt.ctrlKey; - - if (isCtrlCommand && this.graph) { - // Copy. - if (evt.key === "c") { - if (this.#writingToClipboard) { - return; - } - - const selected = this.#graphRenderer.getSelectedChildren(); - if (!selected.length) { - return; - } - - let breadboardGraph = this.graph.raw(); - if (this.subGraphId && breadboardGraph.graphs) { - const subgraphs = breadboardGraph.graphs; - if (subgraphs[this.subGraphId]) { - breadboardGraph = subgraphs[this.subGraphId]; - } else { - console.warn( - `Unable to locate subgraph by name: ${this.subGraphId}` - ); - } - } - - const nodes = breadboardGraph.nodes.filter((node) => { - return selected.find((item) => item.label === node.id); - }); - - const edges = breadboardGraph.edges.filter((edge) => { - return selected.find((item) => { - if (!(item instanceof GraphEdge)) { - return false; - } - - if (!item.edge) { - return false; - } - - return ( - item.edge.from.descriptor.id === edge.from && - item.edge.to.descriptor.id === edge.to - ); - }); - }); - - breadboardGraph.metadata ??= {}; - breadboardGraph.metadata.comments ??= []; - const metadataComments = breadboardGraph.metadata.comments; - const comments = metadataComments.filter((node) => { - return selected.find((item) => item.label === node.id); - }); - - const metadata = { ...breadboardGraph.metadata, comments }; - - this.#writingToClipboard = true; - await navigator.clipboard.writeText( - JSON.stringify( - { - title: breadboardGraph.title, - description: breadboardGraph.description, - version: breadboardGraph.version, - metadata, - edges, - nodes, - }, - null, - 2 - ) - ); - this.#writingToClipboard = false; - } else if (evt.key === "v") { - // Paste. - if (this.#readingFromClipboard) { - return; - } - - this.#graphRenderer.deselectAllChildren(); - - try { - this.#readingFromClipboard = true; - const data = await navigator.clipboard.readText(); - if (!data || !this.graph) { - return; - } - - let graph; - // TODO: This is a kludge, let's be more robust here. - // Maybe like InspectableGraph.isGraphURL(data) or something. - if (data.endsWith(".bgl.json")) { - graph = { - edges: [], - nodes: [ - { - id: this.#createRandomID(data), - type: data, - }, - ], - }; - } else { - graph = JSON.parse(data) as GraphDescriptor; - if (!("edges" in graph && "nodes" in graph)) { - return; - } - } - - const comments = graph.metadata?.comments ?? []; - const nodesAndComments = [...graph.nodes, ...comments]; - nodesAndComments.sort( - ( - nodeA: NodeDescriptor | CommentNode, - nodeB: NodeDescriptor | CommentNode - ) => { - if (nodeA.metadata?.visual && nodeB.metadata?.visual) { - const visualA = nodeA.metadata.visual as Record; - const visualB = nodeB.metadata.visual as Record; - return visualA.x - visualB.x; - } - - if (nodeA.metadata?.visual && !nodeB.metadata?.visual) { - return -1; - } - - if (!nodeA.metadata?.visual && nodeB.metadata?.visual) { - return 1; - } - - return 0; - } - ); - - if (!nodesAndComments.length) { - return; - } - - const leftMostNode = nodesAndComments[0]; - let leftMostVisual = structuredClone( - leftMostNode.metadata?.visual - ) as Record; - if (!leftMostVisual) { - leftMostVisual = { x: 0, y: 0 }; - } - - const leftMostNodeGlobalPosition = this.#graphRenderer.toGlobal({ - x: leftMostVisual.x, - y: leftMostVisual.y, - }); - - // Find the current graph. - let breadboardGraph = this.graph.raw(); - if (this.subGraphId && breadboardGraph.graphs) { - const subgraphs = breadboardGraph.graphs; - if (subgraphs[this.subGraphId]) { - breadboardGraph = subgraphs[this.subGraphId]; - } else { - console.warn( - `Unable to locate subgraph by name: ${this.subGraphId}` - ); - } - } - - if (!breadboardGraph) { - return; - } - - const remappedNodeIds = new Map(); - const edits: EditSpec[] = []; - for (let i = 0; i < graph.nodes.length; i++) { - const node = graph.nodes[i]; - if (!this.#isNodeDescriptor(node)) { - continue; - } - - // Update the node ID so it doesn't clash. - const existingNode = breadboardGraph.nodes.find( - (graphNode) => graphNode.id === node.id - ); - if (existingNode) { - node.id = this.#createRandomID(node.type); - remappedNodeIds.set(existingNode.id, node.id); - } - - node.metadata = node.metadata || {}; - node.metadata.visual = (node.metadata.visual || {}) as Record< - string, - NodeValue - >; - - // Grab the x & y coordinates, delete them, and use them to instruct - // the graph where to place the node when it's added. - const x = (node.metadata.visual["x"] as number) ?? i * 40; - const y = (node.metadata.visual["y"] as number) ?? 0; - - delete node.metadata.visual["x"]; - delete node.metadata.visual["y"]; - - const globalPosition = this.#graphRenderer.toGlobal({ x, y }); - const offset = { - x: globalPosition.x - leftMostNodeGlobalPosition.x, - y: globalPosition.y - leftMostNodeGlobalPosition.y, - }; - - const position = { - x: this.#lastX + offset.x - PASTE_OFFSET, - y: this.#lastY + offset.y - PASTE_OFFSET, - }; - - this.#graphRenderer.setNodeLayoutPosition( - node.id, - "node", - position, - this.collapseNodesByDefault ? "collapsed" : "expanded", - false - ); - this.#graphRenderer.addToAutoSelect(node.id); - - // Ask the graph for the visual positioning because the graph accounts for - // any transforms, whereas our base x & y values do not. - const layout = this.#graphRenderer.getNodeLayoutPosition( - node.id - ) || { - x: 0, - y: 0, - }; - node.metadata.visual.x = layout.x; - node.metadata.visual.y = layout.y; - - edits.push({ type: "addnode", node }); - } - - for (const edge of graph.edges) { - if (!this.#isEdge(edge)) { - continue; - } - - const newEdge = { - from: remappedNodeIds.get(edge.from) ?? edge.from, - to: remappedNodeIds.get(edge.to) ?? edge.to, - in: edge.in ?? "MISSING_WIRE", - out: edge.out ?? "MISSING_WIRE", - }; - - const existingEdge = breadboardGraph.edges.find( - (graphEdge) => - graphEdge.from === newEdge.from && - graphEdge.to === newEdge.to && - graphEdge.out === newEdge.out && - graphEdge.in === newEdge.in - ); - if (existingEdge) { - continue; - } - - if (edge.in === "MISSING_WIRE" || edge.out === "MISSING_WIRE") { - continue; - } - - this.#graphRenderer.addToAutoSelect(edgeToString(newEdge)); - edits.push({ type: "addedge", edge: newEdge }); - } - - if (graph.metadata && graph.metadata.comments) { - breadboardGraph.metadata ??= {}; - breadboardGraph.metadata.comments ??= []; - - const newComments: CommentNode[] = []; - for (const comment of graph.metadata.comments) { - // Update the node ID so it doesn't clash. - const existingNode = breadboardGraph.metadata.comments.find( - (graphNode) => graphNode.id === comment.id - ); - - if (existingNode) { - comment.id = this.#createRandomID("comment"); - } - - // Grab the x & y coordinates, delete them, and use them to instruct - // the graph where to place the node when it's added. - comment.metadata ??= {}; - comment.metadata.visual ??= {}; - - const visual = comment.metadata.visual as Record; - const x = (visual["x"] as number) ?? 0; - const y = (visual["y"] as number) ?? 0; - - delete visual["x"]; - delete visual["y"]; - - const globalPosition = this.#graphRenderer.toGlobal({ x, y }); - const offset = { - x: globalPosition.x - leftMostNodeGlobalPosition.x, - y: globalPosition.y - leftMostNodeGlobalPosition.y, - }; - - const position = { - x: this.#lastX + offset.x - PASTE_OFFSET, - y: this.#lastY + offset.y - PASTE_OFFSET, - }; - - this.#graphRenderer.setNodeLayoutPosition( - comment.id, - "comment", - position, - this.collapseNodesByDefault ? "collapsed" : "expanded", - false - ); - this.#graphRenderer.addToAutoSelect(comment.id); - - // Ask the graph for the visual positioning because the graph accounts for - // any transforms, whereas our base x & y values do not. - const layout = this.#graphRenderer.getNodeLayoutPosition( - comment.id - ) || { - x: 0, - y: 0, - }; - - visual.x = layout.x; - visual.y = layout.y; - - newComments.push(comment); - } - - breadboardGraph.metadata.comments = [ - ...breadboardGraph.metadata.comments, - ...newComments, - ]; - edits.push({ - type: "changegraphmetadata", - metadata: breadboardGraph.metadata, - }); - } - - this.dispatchEvent( - new MultiEditEvent( - edits, - `Paste (#${++this.#pasteCount})`, - this.subGraphId - ) - ); - } catch (err) { - // Not JSON data - ignore. - return; - } finally { - this.#readingFromClipboard = false; - } - } - } - } - - #onPointerDown(evt: Event) { - if (!this.#addButtonRef.value) { - return; - } - - const [top] = evt.composedPath(); - if ( - top instanceof HTMLLabelElement && - top.getAttribute("for") === "add-node" - ) { - return; - } - - this.#addButtonRef.value.checked = false; - } - - #onGraphNodesVisualUpdate(evt: Event) { - const moveEvt = evt as GraphNodesVisualUpdateEvent; - const label = moveEvt.nodes.reduce((prev, curr, idx) => { - return ( - prev + - (idx > 0 ? ", " : "") + - `(${curr.id}, {x: ${curr.x}, y: ${curr.y}, collapsed: ${curr.expansionState}})` - ); - }, ""); - const editsEvt = new MultiEditEvent( - moveEvt.nodes.map((node) => { - switch (node.type) { - case "node": { - const graphNode = this.graph?.nodeById(node.id); - const metadata = (graphNode?.metadata() || {}) as Record< - string, - unknown - >; - - return { - type: "changemetadata", - id: node.id, - metadata: { - ...metadata, - visual: { - x: node.x, - y: node.y, - collapsed: node.expansionState, - }, - }, - }; - } - - case "comment": { - if (!this.graph) { - throw new Error("No active graph - unable to update"); - } - - const metadata = this.graph.metadata() || {}; - const commentNode = metadata.comments?.find( - (commentNode) => commentNode.id === node.id - ); - - if (commentNode && commentNode.metadata) { - commentNode.metadata.visual = { - x: node.x, - y: node.y, - collapsed: node.expansionState, - }; - } - - return { - type: "changegraphmetadata", - metadata, - }; - } - } - }), - `Node multimove: ${label}`, - this.subGraphId - ); - - if (this.readOnly) { - return; - } - - this.dispatchEvent(editsEvt); - } - - #onGraphEdgeAttach(evt: Event) { - const { edge } = evt as GraphEdgeAttachEvent; - this.dispatchEvent( - new EdgeChangeEvent( - "add", - { - from: edge.from.descriptor.id, - to: edge.to.descriptor.id, - out: edge.out, - in: edge.in, - constant: edge.type === "constant", - }, - undefined, - this.subGraphId - ) - ); - } - - #onGraphEdgeDetach(evt: Event) { - const { edge } = evt as GraphEdgeDetachEvent; - this.dispatchEvent( - new EdgeChangeEvent( - "remove", - { - from: edge.from.descriptor.id, - to: edge.to.descriptor.id, - out: edge.out, - in: edge.in, - }, - undefined, - this.subGraphId - ) - ); - } - - #onGraphEdgeChange(evt: Event) { - const { fromEdge, toEdge } = evt as GraphNodeEdgeChangeEvent; - this.dispatchEvent( - new EdgeChangeEvent( - "move", - { - from: fromEdge.from.descriptor.id, - to: fromEdge.to.descriptor.id, - out: fromEdge.out, - in: fromEdge.in, - constant: fromEdge.type === "constant", - }, - { - from: toEdge.from.descriptor.id, - to: toEdge.to.descriptor.id, - out: toEdge.out, - in: toEdge.in, - constant: toEdge.type === "constant", - }, - this.subGraphId - ) - ); - } - - #onGraphNodeDelete(evt: Event) { - const { id } = evt as GraphNodeDeleteEvent; - this.dispatchEvent(new NodeDeleteEvent(id, this.subGraphId)); - } - - #onGraphEntityRemove(evt: Event) { - const { nodes, edges, comments } = evt as GraphEntityRemoveEvent; - const edits: EditSpec[] = []; - - // Remove edges first. - for (const edge of edges) { - edits.push({ - type: "removeedge", - edge: { - from: edge.from.descriptor.id, - to: edge.to.descriptor.id, - out: edge.out, - in: edge.in, - }, - }); - } - - // Remove nodes. - for (const id of nodes) { - edits.push({ type: "removenode", id }); - } - - // Remove comments. - let graph = this.graph?.raw(); - if (this.subGraphId && graph?.graphs) { - graph = graph.graphs[this.subGraphId]; - } - if (graph && graph.metadata) { - graph.metadata.comments ??= []; - graph.metadata.comments = graph.metadata.comments.filter( - (comment) => !comments.includes(comment.id) - ); - edits.push({ - type: "changegraphmetadata", - metadata: graph.metadata, - }); - } - - // Create some comments for bookkeeping. - const nodesLabel = nodes.length ? `#${nodes.join(", #")}` : "No nodes"; - const edgesLabel = edges.length - ? edges.reduce((prev, curr, idx) => { - return ( - prev + - (idx > 0 ? ", " : "") + - edgeToString({ - from: curr.from.descriptor.id, - to: curr.to.descriptor.id, - out: curr.out, - in: curr.in, - }) - ); - }, "") - : "No edges"; - const commentsLabel = comments.length - ? `#${comments.join(", #")}` - : "No comments"; - - this.dispatchEvent( - new MultiEditEvent( - edits, - `Delete (${nodesLabel}) (${edgesLabel}) (${commentsLabel})`, - this.subGraphId - ) - ); - } - - #onGraphNodeEdit(evt: Event) { - const { id, port, x, y, addHorizontalClickClearance } = - evt as GraphNodeEditEvent; - - this.dispatchEvent( - new NodeConfigurationUpdateRequestEvent( - id, - this.subGraphId, - port, - x, - y, - addHorizontalClickClearance - ) - ); - } - - #onGraphEdgeValueSelected(evt: Event) { - const { value, schema, x, y } = evt as GraphEdgeValueSelectedEvent; - this.dispatchEvent(new EdgeValueSelectedEvent(value, schema, x, y)); - } - - #onGraphNodeActivitySelected(evt: Event) { - const { nodeTitle, runId } = evt as GraphNodeActivitySelectedEvent; - this.dispatchEvent(new NodeActivitySelectedEvent(nodeTitle, runId)); - } - - #onDragOver(evt: DragEvent) { - evt.preventDefault(); - } - - #onDrop(evt: DragEvent) { - const [top] = evt.composedPath(); - if (!(top instanceof HTMLCanvasElement)) { - return; - } - - evt.preventDefault(); - const type = evt.dataTransfer?.getData(DATA_TYPE); - if (!type || !this.#graphRenderer) { - return; - } - - const id = this.#createRandomID(type); - const x = evt.pageX - this.#left + window.scrollX; - const y = evt.pageY - this.#top - window.scrollY; - - this.#graphRenderer.deselectAllChildren(); - - // Store the middle of the node for later. - this.#graphRenderer.setNodeLayoutPosition( - id, - type === "comment" ? "comment" : "node", - { x, y }, - this.collapseNodesByDefault ? "collapsed" : "expanded", - true - ); - - // Ask the graph for the visual positioning because the graph accounts for - // any transforms, whereas our base x & y values do not. - const layout = this.#graphRenderer.getNodeLayoutPosition(id) || { - x: 0, - y: 0, - }; - - const configuration = getDefaultConfiguration(type); - this.dispatchEvent( - new NodeCreateEvent(id, type, this.subGraphId, configuration, { - visual: { - x: layout.x, - y: layout.y, - collapsed: this.collapseNodesByDefault, - }, - }) - ); - } - - #createRandomID(type: string) { - const randomId = globalThis.crypto.randomUUID(); - const nextNodeId = randomId.split("-"); - // Now that types could be URLs, we need to make them a bit - // less verbose. - if (type.includes(":") || type.includes("#")) { - // probably a URL, so let's create a nice short name from the URL - try { - const url = new URL(type); - const name = url.pathname - .split("/") - .pop() - ?.replace(".bgl.json", "") - .slice(0, 15); - if (name) { - return `${name}-${nextNodeId[0]}`; - } - } catch (e) { - // Ignore. - } - return `board-${nextNodeId[0]}`; - } - // TODO: Check for clashes - return `${type}-${nextNodeId[0]}`; - } - - #onResize() { - const bounds = this.getBoundingClientRect(); - this.#top = bounds.top; - this.#left = bounds.left; - } - - #proposeNewSubGraph() { - const newSubGraphName = prompt( - "What would you like to call this sub board?" - ); - if (!newSubGraphName) { - return; - } - - this.dispatchEvent(new SubGraphCreateEvent(newSubGraphName)); - } - - #dispatchActivityMarkerEvent(forceOn = false) { - if (!this.#activityMarkerRef.value) { - return; - } - - const bounds = this.#activityMarkerRef.value.getBoundingClientRect(); - this.dispatchEvent( - new ToggleBoardActivityEvent( - bounds.left + bounds.width / 2, - bounds.top - 10, - forceOn - ) - ); - } - - firstUpdated(): void { - this.#onResizeBound(); - } - - render() { - this.#graphRenderer.topGraphResult = this.subGraphId - ? null - : this.topGraphResult; - - if (this.#graphRenderer) { - this.#graphRenderer.invertZoomScrollDirection = - this.invertZoomScrollDirection; - } - - const rawGraph = this.graph?.raw(); - const subGraphs: SubGraphs | null = rawGraph?.graphs - ? rawGraph.graphs - : null; - - let showSubGraphSelector = true; - if ( - this.hideSubboardSelectorWhenEmpty && - (!subGraphs || (subGraphs && Object.entries(subGraphs).length === 0)) - ) { - showSubGraphSelector = false; - } - - const isRunning = this.topGraphResult - ? this.topGraphResult.status === "running" || - this.topGraphResult.status === "paused" - : false; - - let saveButton: HTMLTemplateResult | symbol = nothing; - try { - if (this.capabilities && this.capabilities.save) { - saveButton = html``; - } else { - saveButton = html``; - } - } catch (err) { - // If there are any problems with the URL, etc, don't offer the save button. - } - - let overflowMenu: HTMLTemplateResult | symbol = nothing; - if (this.showOverflowMenu) { - const actions: Array<{ - title: string; - name: string; - icon: string; - disabled?: boolean; - }> = [ - { - title: "Edit Board Details", - name: "edit-board-details", - icon: "edit", - }, - { - title: "Copy Board Contents", - name: "copy-board-contents", - icon: "copy", - }, - { - title: "Copy Board URL", - name: "copy-to-clipboard", - icon: "copy", - }, - { - title: "Copy Tab URL", - name: "copy-tab-to-clipboard", - icon: "copy", - }, - { - title: "Download Board", - name: "download", - icon: "download", - }, - ]; - - if (this.capabilities) { - if (this.capabilities.delete) { - actions.push({ - title: "Delete Board", - name: "delete", - icon: "delete", - }); - } - - if (this.capabilities.save) { - actions.push({ - title: "Save As...", - name: "save-as", - icon: "save", - }); - } - } - - if (this.extendedCapabilities && this.extendedCapabilities.preview) { - actions.push({ - title: "Copy Preview URL", - name: "preview", - icon: "preview", - }); - } - - overflowMenu = html` { - this.showOverflowMenu = false; - }} - @bboverflowmenuaction=${() => { - this.showOverflowMenu = false; - }} - >`; - } - - let isInputPending = false; - let isError = false; - const newestEvent = this.run?.events.at(-1); - if (newestEvent) { - isInputPending = - newestEvent.type === "node" && - newestEvent.node.descriptor.type === "input"; - isError = newestEvent.type === "error"; - } - - return html`${until(this.#processGraph())} - ${ - this.showControls && this.graph !== null - ? html` - - - - - - ${this.readOnly - ? nothing - : html` -
    - - - - ${showSubGraphSelector - ? html`
    - ` - : nothing} - - -
    - - - - ${saveButton} - -
    - ${overflowMenu} - `} - ${this.graph !== null - ? html` -
    - - - - - { - if (!(evt.target instanceof HTMLInputElement)) { - return; - } - - if (!this.#nodeSelectorRef.value) { - return; - } - - const nodeSelector = this.#nodeSelectorRef.value; - nodeSelector.inert = !evt.target.checked; - - if (!evt.target.checked) { - return; - } - nodeSelector.selectSearchInput(); - }} - /> - - - { - const id = this.#createRandomID(evt.nodeType); - this.dispatchEvent( - new NodeCreateEvent(id, evt.nodeType) - ); - }} - > -
    - - ${this.readOnly - ? html`
    Read-only View` - : nothing} - ` - : nothing}` - : nothing - } - `; - } -} diff --git a/packages/shared-ui/src/elements/editor/fancy-json.ts b/packages/shared-ui/src/elements/editor/fancy-json.ts deleted file mode 100644 index 792e89a85a0..00000000000 --- a/packages/shared-ui/src/elements/editor/fancy-json.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { JsonSerializable } from "@breadboard-ai/build/internal/type-system/type.js"; -import { LitElement, css, html, nothing } from "lit"; -import { customElement, property } from "lit/decorators.js"; - -export interface FancyJsonAnnotation { - path: Array; - partName: string; -} - -/** - * Displays some JSON with highlighting. - */ -@customElement("bb-fancy-json") -export class FancyJson extends LitElement { - @property({ type: Object }) - json?: JsonSerializable; - - @property({ type: Number }) - indent = 2; - - #annotations?: FancyJsonAnnotation[]; - #annotationsBySerializedPath = new Map(); - - @property({ type: Array }) - get annotations(): FancyJsonAnnotation[] | undefined { - return this.#annotations; - } - set annotations(annotations: FancyJsonAnnotation[] | undefined) { - this.#annotations = annotations; - this.#annotationsBySerializedPath.clear(); - if (annotations !== undefined) { - for (const annotation of annotations) { - const key = JSON.stringify(annotation.path); - const val = this.#annotationsBySerializedPath.get(key); - if (val === undefined) { - this.#annotationsBySerializedPath.set(key, [annotation]); - } else { - val.push(annotation); - } - } - } - } - - static styles = css` - pre { - text-wrap: wrap; - } - `; - - override render() { - if (!this.json) { - return nothing; - } - return this.#renderJsonValue(this.json, 1, []); - } - - #renderJsonValue( - value: JsonSerializable, - indent: number, - path: Array - ): unknown { - const parts = []; - - switch (typeof value) { - case "string": { - parts.push(JSON.stringify(value)); - break; - } - case "number": - case "boolean": { - parts.push(value); - break; - } - - case "object": { - if (value === null) { - parts.push("null"); - } else if (Array.isArray(value)) { - parts.push("["); - if (value.length > 0) { - for (let v = 0; v < value.length; v++) { - parts.push("\n"); - for (let i = 0; i < indent; i++) { - parts.push(" "); - } - const val = value[v]; - path.push(v); - parts.push(this.#renderJsonValue(val, indent + 1, path)); - path.pop(); - if (v < value.length - 1) { - parts.push(","); - } else { - parts.push("\n"); - } - } - for (let i = 1; i < indent; i++) { - parts.push(" "); - } - } - parts.push("]"); - } else { - parts.push("{"); - const entries = Object.entries(value); - if (entries.length > 0) { - for (let e = 0; e < entries.length; e++) { - parts.push("\n"); - for (let i = 0; i < indent; i++) { - parts.push(" "); - } - const [key, val] = entries[e]; - parts.push(JSON.stringify(key), ": "); - path.push(key); - parts.push(this.#renderJsonValue(val, indent + 1, path)); - path.pop(); - if (e < entries.length - 1) { - parts.push(","); - } else { - parts.push("\n"); - } - } - for (let i = 1; i < indent; i++) { - parts.push(" "); - } - } - parts.push("}"); - } - break; - } - default: { - value satisfies never; - } - } - - if (this.annotations !== undefined) { - const serializedPath = JSON.stringify(path); - const annotations = this.#annotationsBySerializedPath.get(serializedPath); - if (annotations !== undefined) { - const partNames = []; - for (const annotation of annotations) { - if (annotation.partName) { - partNames.push(annotation.partName); - } - } - return html`${parts}`; - } - } - - return parts; - } -} diff --git a/packages/shared-ui/src/elements/editor/graph-assets.ts b/packages/shared-ui/src/elements/editor/graph-assets.ts deleted file mode 100644 index df772dd60be..00000000000 --- a/packages/shared-ui/src/elements/editor/graph-assets.ts +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as PIXI from "pixi.js"; - -const ASSET_LIST = new Map([ - ["value", "/third_party/icons/graph/value-48px.svg"], - ["input", "/third_party/icons/graph/input-48px.svg"], - ["output", "/third_party/icons/graph/output-48px.svg"], - ["js", "/third_party/icons/graph/js-48px.svg"], - ["smart-toy", "/third_party/icons/graph/smart-toy-48px.svg"], - ["merge-type", "/third_party/icons/graph/merge-type-48px.svg"], - ["human", "/third_party/icons/graph/human-48px.svg"], - ["laps", "/third_party/icons/graph/laps-48px.svg"], - ["nano", "/third_party/icons/graph/nano-48px.svg"], - ["google-drive", "/third_party/icons/graph/google-drive-48px.svg"], - ["code-blocks", "/third_party/icons/graph/code-blocks-48px.svg"], -]); - -type AssetMap = Map; - -export class GraphAssets { - static assetPrefix = "~"; - static #instance: GraphAssets; - static instance() { - if (!this.#instance) { - this.#instance = new GraphAssets(); - } - return this.#instance; - } - - #assets: AssetMap = new Map(); - #loaded: Promise = Promise.resolve(); - - loadAssets(assetPrefix: string) { - GraphAssets.assetPrefix = assetPrefix; - const loadedAssets = [...ASSET_LIST.entries()].map( - async ([name, path]): Promise<[string, PIXI.Texture | null]> => { - try { - const texture = await PIXI.Assets.load( - `${GraphAssets.assetPrefix}${path}` - ); - return [name, texture]; - } catch (e) { - return [name, null]; - } - } - ); - - this.#loaded = Promise.all(loadedAssets).then((vals) => { - this.#assets = new Map( - vals.filter((v) => v[1] !== null) as [string, PIXI.Texture][] - ); - }); - } - - // Not to be instantiated directly. - private constructor() {} - - get loaded() { - return this.#loaded; - } - - get(name: string) { - return this.#assets.get(name) || null; - } - - has(name: string) { - return this.#assets.has(name); - } -} diff --git a/packages/shared-ui/src/elements/editor/graph-comment.ts b/packages/shared-ui/src/elements/editor/graph-comment.ts deleted file mode 100644 index 70c74b56d99..00000000000 --- a/packages/shared-ui/src/elements/editor/graph-comment.ts +++ /dev/null @@ -1,378 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as PIXI from "pixi.js"; -import { DBL_CLICK_DELTA, getGlobalColor } from "./utils.js"; -import { ComponentExpansionState, GRAPH_OPERATIONS } from "./types.js"; -import MarkdownIt from "markdown-it"; - -const markdown = MarkdownIt(); -const backgroundColor = getGlobalColor("--bb-ui-50"); -const emptyTextColor = getGlobalColor("--bb-neutral-600"); -const textColor = getGlobalColor("--bb-neutral-800"); -const linkColor = getGlobalColor("--bb-ui-500"); -const defaultBorderColor = getGlobalColor("--bb-neutral-500"); -const selectedBorderColor = getGlobalColor("--bb-ui-600"); - -type LinkData = { - url: string; - rects: DOMRectList; -}; - -/** - * This class acts a link proxy. Under the hood Pixi.js uses a Foreign Object in - * SVG to do the rendering for an HTMLText instance. We replicate that here to - * derive the rectangles for any elements. - * - * To implement this we create a temporary iframe clipped so it renders but does - * not appear within the viewport. This iframe contains markup with the same - * styles that Pixi used. We then interrogate the anchor elements and their - * rects, providing that back to the main GraphComment class. - */ -class GraphCommentProxy { - #src: string | null = null; - #linkProxy: HTMLIFrameElement | null = null; - readonly hitAreaData: Promise | null = null; - - constructor(padding: number, html: string, styles: string) { - this.#linkProxy = document.createElement("iframe"); - this.#linkProxy.setAttribute("seamless", "seamless"); - this.#linkProxy.style["position"] = "fixed"; - this.#linkProxy.style["top"] = "0"; - this.#linkProxy.style["left"] = "0"; - this.#linkProxy.style["zIndex"] = "10000"; - this.#linkProxy.style["clipPath"] = "rect(0 0 0 0)"; - this.#linkProxy.style["pointerEvents"] = "none"; - document.body.appendChild(this.#linkProxy); - - const proxyDoc = this.#linkProxy.contentDocument; - if (!proxyDoc) { - console.warn("Unable to access link proxy - no content document"); - return; - } - - this.#src = URL.createObjectURL( - new Blob( - [ - ` - -
    ${html}
    `, - ], - { type: "text/html" } - ) - ); - - this.#linkProxy.src = this.#src; - - this.hitAreaData = new Promise((resolve, reject) => { - if (!this.#linkProxy) { - reject("No link proxy"); - return; - } - - this.#linkProxy.onload = () => { - if (!this.#linkProxy || !this.#linkProxy.contentDocument) { - reject("No link proxy"); - return; - } - - const shapes: Array<{ url: string; rects: DOMRectList }> = []; - const links = [ - ...this.#linkProxy.contentDocument.querySelectorAll("a"), - ]; - for (const link of links) { - const linkData: LinkData = { - url: link.href, - rects: link.getClientRects(), - }; - - shapes.push(linkData); - } - - resolve(shapes); - }; - }); - } - - clean() { - try { - if (this.#src) { - URL.revokeObjectURL(this.#src); - } - - if (this.#linkProxy) { - this.#linkProxy.remove(); - this.#linkProxy = null; - } - } catch (err) { - console.warn("Error cleaning link proxy"); - console.warn(err); - } - } -} - -export class GraphComment extends PIXI.Container { - #maxWidth = 220; - #isDirty = true; - #lineWidth = 1; - #selectedLineWidth = 2; - #borderRadius = 8; - #padding = 12; - #text: string | null = null; - #textLabel = new PIXI.HTMLText({ - text: "", - style: { - fontSize: 14, - fontFamily: "Arial", - fill: emptyTextColor, - wordWrap: true, - breakWords: true, - wordWrapWidth: this.#maxWidth - 2 * this.#padding, - lineHeight: 20, - tagStyles: { - a: { - fill: linkColor, - fontWeight: "bold", - }, - }, - }, - }); - #selected = false; - #background = new PIXI.Graphics(); - #defaultBorderColor = defaultBorderColor; - #selectedBorderColor = selectedBorderColor; - #hitAreaData: LinkData[] = []; - #hitAreas = new PIXI.Container(); - #lastClickTime = 0; - - expansionState: ComponentExpansionState = "expanded"; - readOnly = false; - - constructor() { - super(); - - this.eventMode = "static"; - this.onRender = () => { - if (!this.#isDirty) { - return; - } - this.#isDirty = false; - this.#background.clear(); - for (const child of this.#hitAreas.removeChildren()) { - child.destroy(); - } - - this.#draw(); - this.emit(GRAPH_OPERATIONS.GRAPH_COMMENT_DRAWN); - }; - - this.#textLabel.eventMode = "none"; - this.#background.eventMode = "auto"; - - this.addChild(this.#background); - this.addChild(this.#textLabel); - this.addChild(this.#hitAreas); - - this.#textLabel.x = this.#padding; - this.#textLabel.y = this.#padding; - this.#hitAreas.x = this.#padding; - this.#hitAreas.y = this.#padding; - } - - addPointerEventListeners() { - let dragStart: PIXI.PointData | null = null; - let originalPosition: PIXI.ObservablePoint | null = null; - let hasMoved = false; - - this.addEventListener("click", (evt: PIXI.FederatedMouseEvent) => { - if (this.readOnly) { - return; - } - - const clickDelta = window.performance.now() - this.#lastClickTime; - this.#lastClickTime = window.performance.now(); - - if (clickDelta > DBL_CLICK_DELTA) { - return; - } - - this.emit( - GRAPH_OPERATIONS.GRAPH_COMMENT_EDIT_REQUESTED, - this.label, - evt.clientX, - evt.clientY - ); - }); - - this.addEventListener("pointerover", () => { - if (this.readOnly) { - return; - } - - this.cursor = "grabbing"; - }); - - this.addEventListener("pointerdown", (evt: PIXI.FederatedPointerEvent) => { - if (!(evt.target instanceof GraphComment) || this.readOnly) { - return; - } - - hasMoved = false; - dragStart = evt.global.clone(); - originalPosition = this.position.clone(); - }); - - this.addEventListener( - "globalpointermove", - (evt: PIXI.FederatedPointerEvent) => { - if (!dragStart || !originalPosition) { - return; - } - - const scale = this.worldTransform.a; - const dragPosition = evt.global; - const dragDeltaX = (dragPosition.x - dragStart.x) / scale; - const dragDeltaY = (dragPosition.y - dragStart.y) / scale; - - this.x = Math.round(originalPosition.x + dragDeltaX); - this.y = Math.round(originalPosition.y + dragDeltaY); - hasMoved = true; - - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_MOVED, this.x, this.y, false); - } - ); - - const onPointerUp = () => { - dragStart = null; - originalPosition = null; - if (!hasMoved) { - return; - } - - hasMoved = false; - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_MOVED, this.x, this.y, true); - }; - - this.addEventListener("pointerupoutside", onPointerUp); - this.addEventListener("pointerup", onPointerUp); - } - - set selected(selected: boolean) { - if (this.#selected === selected) { - return; - } - - this.#selected = selected; - this.#isDirty = true; - } - - get selected() { - return this.#selected; - } - - set text(text: string | null) { - if (text === this.#text) { - return; - } - - this.#isDirty = true; - this.#text = text; - if (!text) { - this.#textLabel.text = "No comment"; - this.#textLabel.style.fill = emptyTextColor; - this.#textLabel.style.fontStyle = "italic"; - return; - } - - const renderedText = markdown.renderInline(text); - this.#textLabel.text = renderedText; - this.#textLabel.style.fill = textColor; - this.#textLabel.style.fontStyle = "normal"; - - // Only create a proxy if the node looks to include links. - if (!renderedText.includes('href="')) { - return; - } - - const proxy = new GraphCommentProxy( - this.#padding, - renderedText, - this.#textLabel.style.cssStyle - ); - - proxy.hitAreaData?.then((hitAreas) => { - this.#hitAreaData = hitAreas; - this.#isDirty = true; - - proxy.clean(); - }); - } - - get text() { - return this.#text; - } - - #draw() { - const width = Math.max(100, this.#textLabel.width + this.#padding * 2); - const height = this.#textLabel.height + this.#padding * 2; - - const borderWidth = this.selected - ? this.#selectedLineWidth - : this.#lineWidth; - const borderColor = this.selected - ? this.#selectedBorderColor - : this.#defaultBorderColor; - - this.#background.beginPath(); - this.#background.roundRect(0, 0, width, height, this.#borderRadius); - this.#background.stroke({ color: borderColor, width: borderWidth }); - this.#background.fill({ color: backgroundColor, alpha: 1 }); - this.#background.closePath(); - - this.#drawHitAreas(); - } - - #drawHitAreas() { - for (const hitAreaItem of this.#hitAreaData) { - const hitArea = new PIXI.Graphics(); - hitArea.label = hitAreaItem.url; - hitArea.cursor = "pointer"; - - for (const rect of hitAreaItem.rects) { - hitArea.beginPath(); - hitArea.rect(rect.x, rect.y, rect.width, rect.height); - hitArea.closePath(); - hitArea.fill({ color: 0xff00ff, alpha: 0 }); - } - - hitArea.addEventListener( - "pointerup", - (evt: PIXI.FederatedPointerEvent) => { - const url = evt.target.label; - if (url.startsWith("board:")) { - this.emit( - GRAPH_OPERATIONS.GRAPH_BOARD_LINK_CLICKED, - url.replace(/board:/, "") - ); - return; - } - - try { - const parsedUrl = new URL(url); - window.open(parsedUrl.href, "_blank", "noopener"); - } catch (err) { - console.warn(`Unable to parse URL from comment: ${url}`); - console.warn(err); - } - } - ); - - this.#hitAreas.addChild(hitArea); - } - } -} diff --git a/packages/shared-ui/src/elements/editor/graph-edge.ts b/packages/shared-ui/src/elements/editor/graph-edge.ts deleted file mode 100644 index 209f3c53a79..00000000000 --- a/packages/shared-ui/src/elements/editor/graph-edge.ts +++ /dev/null @@ -1,787 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - InspectableEdgeType, - NodeValue, - Schema, -} from "@google-labs/breadboard"; -import * as PIXI from "pixi.js"; -import { GraphNode } from "./graph-node.js"; -import { getGlobalColor } from "./utils.js"; -import { EdgeData, cloneEdgeData } from "../../types/types.js"; -import { GraphAssets } from "./graph-assets.js"; -import { GRAPH_OPERATIONS } from "./types.js"; - -const edgeColorWithValues = getGlobalColor("--bb-input-600"); -const edgeColorSelected = getGlobalColor("--bb-ui-600"); -const edgeColorOrdinary = getGlobalColor("--bb-neutral-400"); -const edgeColorConstant = getGlobalColor("--bb-ui-200"); -const edgeColorControl = getGlobalColor("--bb-boards-200"); -const edgeColorStar = getGlobalColor("--bb-inputs-200"); -const edgeColorInvalid = getGlobalColor("--bb-warning-500"); - -const ICON_SCALE = 0.33; - -/** - * Calculates an [x,y] pair of points from start to end via the control point. - * Per the math, this is defined as: - * - * (1-t)² * start + 2(1 - t) * t * cp + t² * end. - * - * @see https://en.wikipedia.org/wiki/B%C3%A9zier_curve - */ -function calculatePointsOnQuadraticBezierCurve( - startX: number, - startY: number, - cpX: number, - cpY: number, - endX: number, - endY: number, - from: number, - to: number, - step: number -) { - if (from > to || from < 0 || from > 1 || to < 0 || to > 1) { - throw new Error( - "from must be less than to, and both must be between 0 and 1" - ); - } - - const points: number[] = []; - for (let t = from; t <= to; t += step) { - points.push( - (1 - t) ** 2 * startX + 2 * (1 - t) * t * cpX + t ** 2 * endX, - (1 - t) ** 2 * startY + 2 * (1 - t) * t * cpY + t ** 2 * endY - ); - } - return points; -} - -/** - * Calculates an [x,y] pair of points from start to end via two control points. - * Per the math, this is defined as: - * - * (1-t)³ * start + 3(1 - t)² * t * cp + 3(1 - t) * t² * cp + t³ * end. - * - * @see https://en.wikipedia.org/wiki/B%C3%A9zier_curve - */ -function calculatePointsOnCubicBezierCurve( - startX: number, - startY: number, - cp1X: number, - cp1Y: number, - cp2X: number, - cp2Y: number, - endX: number, - endY: number, - from: number, - to: number, - step: number -) { - if (from > to || from < 0 || from > 1 || to < 0 || to > 1) { - throw new Error( - "from must be less than to, and both must be between 0 and 1" - ); - } - - const points: number[] = []; - for (let t = from; t <= to; t += step) { - points.push( - (1 - t) ** 3 * startX + - 3 * (1 - t) ** 2 * t * cp1X + - 3 * (1 - t) * t ** 2 * cp2X + - t ** 3 * endX, - - (1 - t) ** 3 * startY + - 3 * (1 - t) ** 2 * t * cp1Y + - 3 * (1 - t) * t ** 2 * cp2Y + - t ** 3 * endY - ); - } - return points; -} - -export class GraphEdge extends PIXI.Container { - #isDirty = true; - #edge: EdgeData | null = null; - #overrideColor: number | null = null; - #loopBackPadding = 30; - #loopBackCurveRadius = 10; - #overrideInLocation: PIXI.ObservablePoint | null = null; - #overrideOutLocation: PIXI.ObservablePoint | null = null; - #type: InspectableEdgeType | null = null; - #selected = false; - #invalid = false; - #edgeGraphic = new PIXI.Graphics(); - #valueSelector = new PIXI.Graphics(); - #valueSprite: PIXI.Sprite | null; - #schema: Schema | null = null; - #value: NodeValue[] | null = null; - #hitAreaSpacing = 6; - - readOnly = false; - - constructor( - public fromNode: GraphNode, - public toNode: GraphNode, - public temporary = false - ) { - super(); - - this.eventMode = "static"; - this.onRender = () => { - if (!this.#isDirty) { - return; - } - this.#edgeGraphic.clear(); - this.#draw(); - this.#isDirty = false; - }; - - this.#edgeGraphic.addEventListener("pointerover", () => { - if (this.readOnly) { - return; - } - - this.#edgeGraphic.cursor = "pointer"; - }); - - this.#valueSelector.addEventListener( - "pointerdown", - (evt: PIXI.FederatedPointerEvent) => { - this.emit( - GRAPH_OPERATIONS.GRAPH_EDGE_VALUE_SELECTED, - this.value, - this.schema, - evt.x, - evt.y - ); - } - ); - - const texture = GraphAssets.instance().get("value"); - this.#valueSprite = texture ? new PIXI.Sprite(texture) : null; - - this.#edgeGraphic.label = "GraphEdge"; - this.#edgeGraphic.eventMode = "static"; - - this.addChild(this.#edgeGraphic); - this.addChild(this.#valueSelector); - - if (this.#valueSprite) { - this.addChild(this.#valueSprite); - this.#valueSprite.scale.x = ICON_SCALE; - this.#valueSprite.scale.y = ICON_SCALE; - this.#valueSprite.eventMode = "none"; - this.#valueSprite.visible = false; - } - } - - set edge(edge: EdgeData | null) { - // Since the `edge` is a stable instance, make a copy of the edge to avoid - // modifying the original. - this.#edge = cloneEdgeData(edge); - this.#isDirty = true; - } - - get selected() { - return this.#selected; - } - - set selected(selected: boolean) { - this.#selected = selected; - this.#isDirty = true; - } - - get value() { - return this.#value; - } - - set value(value: NodeValue[] | null) { - this.#value = value; - this.#isDirty = true; - } - - get schema() { - return this.#schema; - } - - set schema(schema: Schema | null) { - this.#schema = schema; - this.#isDirty = true; - } - - get invalid() { - return this.#invalid; - } - - set invalid(invalid: boolean) { - this.#invalid = invalid; - this.#isDirty = true; - } - - get edge() { - return this.#edge; - } - - set overrideColor(overrideColor: number | null) { - if (overrideColor === this.#overrideColor) { - return; - } - - this.#overrideColor = overrideColor; - this.#isDirty = true; - } - - get overrideColor() { - return this.#overrideColor; - } - - set overrideInLocation(overrideInLocation: PIXI.ObservablePoint | null) { - if (overrideInLocation === this.#overrideInLocation) { - return; - } - - this.#overrideInLocation = overrideInLocation; - this.#isDirty = true; - } - - get overrideInLocation() { - return this.#overrideInLocation; - } - - set overrideOutLocation(overrideOutLocation: PIXI.ObservablePoint | null) { - if (overrideOutLocation === this.#overrideOutLocation) { - return; - } - - this.#overrideOutLocation = overrideOutLocation; - this.#isDirty = true; - } - - get overrideOutLocation() { - return this.#overrideOutLocation; - } - - set type(type: InspectableEdgeType | null) { - if (type === this.#type) { - return; - } - - this.#type = type; - this.#isDirty = true; - } - - get type() { - return this.#type; - } - - forceRedraw() { - this.#isDirty = true; - } - - #draw() { - if (!this.#edge) { - return; - } - - let inLocation = this.toNode.inPortLocation(this.#edge.in); - let outLocation = this.fromNode.outPortLocation(this.#edge.out); - - if (this.#overrideInLocation) { - inLocation = this.#overrideInLocation; - } - - if (this.#overrideOutLocation) { - outLocation = this.#overrideOutLocation; - } - - if (!(outLocation && inLocation)) { - return; - } - - if (!this.fromNode?.position || !this.toNode?.position) { - // Occasionally, we might be drawing an edge between nodes that have - // been destroyed. In this case, we should not attempt to draw the edge. - return; - } - - // Take a copy rather than modifying the original values. - outLocation = outLocation.clone(); - inLocation = inLocation.clone(); - - // Convert to graph-centric values. - outLocation.x += this.fromNode.position.x; - outLocation.y += this.fromNode.position.y; - - inLocation.x += this.toNode.position.x; - inLocation.y += this.toNode.position.y; - - let edgeWidth = 1; - let edgeColor = edgeColorOrdinary; - switch (this.#type) { - case "control": { - edgeColor = edgeColorControl; - break; - } - - case "constant": { - edgeColor = edgeColorConstant; - break; - } - - case "star": { - edgeColor = edgeColorStar; - break; - } - } - - if (this.invalid) { - edgeColor = edgeColorInvalid; - } - - if (this.#overrideColor) { - edgeColor = this.#overrideColor; - } - - if (this.value && this.value.length > 0) { - edgeColor = edgeColorWithValues; - edgeWidth = 2; - } - - if (this.selected) { - edgeColor = edgeColorSelected; - } - - this.#valueSelector.clear(); - this.#valueSelector.beginPath(); - this.#valueSelector.circle(0, 0, 10); - this.#valueSelector.closePath(); - this.#valueSelector.fill({ color: edgeColor }); - this.#valueSelector.eventMode = "static"; - this.#valueSelector.cursor = "pointer"; - this.#valueSelector.visible = false; - - this.#edgeGraphic.setStrokeStyle({ width: edgeWidth, color: edgeColor }); - - const midY = Math.round((inLocation.y - outLocation.y) * 0.5); - const ndx = outLocation.x - inLocation.x; - const ndy = outLocation.y - inLocation.y; - const nodeDistance = Math.sqrt(ndx * ndx + ndy * ndy); - const padding = Math.min(nodeDistance * 0.18, 65); - - // Loopback. - if ( - this.fromNode === this.toNode && - !this.#overrideInLocation && - !this.#overrideOutLocation - ) { - // Line. - this.#edgeGraphic.beginPath(); - this.#edgeGraphic.moveTo(outLocation.x, outLocation.y); - this.#edgeGraphic.lineTo( - outLocation.x + this.#loopBackPadding - this.#loopBackCurveRadius, - outLocation.y - ); - this.#edgeGraphic.quadraticCurveTo( - outLocation.x + this.#loopBackPadding, - outLocation.y, - outLocation.x + this.#loopBackPadding, - outLocation.y + this.#loopBackCurveRadius - ); - this.#edgeGraphic.lineTo( - outLocation.x + this.#loopBackPadding, - this.fromNode.y + - this.fromNode.height + - this.#loopBackPadding - - this.#loopBackCurveRadius - ); - this.#edgeGraphic.quadraticCurveTo( - outLocation.x + this.#loopBackPadding, - this.fromNode.y + this.fromNode.height + this.#loopBackPadding, - outLocation.x + this.#loopBackPadding - this.#loopBackCurveRadius, - this.fromNode.y + this.fromNode.height + this.#loopBackPadding - ); - - this.#edgeGraphic.lineTo( - inLocation.x - this.#loopBackPadding + this.#loopBackCurveRadius, - this.fromNode.y + this.fromNode.height + this.#loopBackPadding - ); - this.#edgeGraphic.quadraticCurveTo( - inLocation.x - this.#loopBackPadding, - this.fromNode.y + this.fromNode.height + this.#loopBackPadding, - inLocation.x - this.#loopBackPadding, - this.fromNode.y + - this.fromNode.height + - this.#loopBackPadding - - this.#loopBackCurveRadius - ); - - this.#edgeGraphic.lineTo( - inLocation.x - this.#loopBackPadding, - inLocation.y + this.#loopBackCurveRadius - ); - this.#edgeGraphic.quadraticCurveTo( - inLocation.x - this.#loopBackPadding, - inLocation.y, - inLocation.x - this.#loopBackPadding + this.#loopBackCurveRadius, - inLocation.y - ); - - this.#edgeGraphic.lineTo(inLocation.x, inLocation.y); - this.#edgeGraphic.stroke(); - this.#edgeGraphic.closePath(); - - // Hit Area. - this.#edgeGraphic.hitArea = new PIXI.Polygon([ - outLocation.x, - outLocation.y - this.#hitAreaSpacing, - - outLocation.x + this.#loopBackPadding + this.#hitAreaSpacing, - outLocation.y - this.#hitAreaSpacing, - - outLocation.x + this.#loopBackPadding + this.#hitAreaSpacing, - this.fromNode.y + - this.fromNode.height + - this.#loopBackPadding + - this.#hitAreaSpacing, - - inLocation.x - this.#loopBackPadding - this.#hitAreaSpacing, - this.fromNode.y + - this.fromNode.height + - this.#loopBackPadding + - this.#hitAreaSpacing, - - inLocation.x - this.#loopBackPadding - this.#hitAreaSpacing, - inLocation.y - this.#hitAreaSpacing, - - inLocation.x, - inLocation.y - this.#hitAreaSpacing, - - inLocation.x, - inLocation.y + this.#hitAreaSpacing, - - inLocation.x - this.#loopBackPadding + this.#hitAreaSpacing, - inLocation.y + this.#hitAreaSpacing, - - inLocation.x - this.#loopBackPadding + this.#hitAreaSpacing, - this.fromNode.y + - this.fromNode.height + - this.#loopBackPadding - - this.#hitAreaSpacing, - - outLocation.x + this.#loopBackPadding - this.#hitAreaSpacing, - this.fromNode.y + - this.fromNode.height + - this.#loopBackPadding - - this.#hitAreaSpacing, - - outLocation.x + this.#loopBackPadding - this.#hitAreaSpacing, - outLocation.y + this.#hitAreaSpacing, - - outLocation.x, - outLocation.y + this.#hitAreaSpacing, - ]); - return; - } - - // All other cases. - // First calculate the line segments. - const pivotA = { - x: - outLocation.x + - Math.max(padding, (inLocation.x - outLocation.x) * 0.25), - y: outLocation.y + midY * 0.5, - }; - - const midA = { - x: Math.max( - outLocation.x, - outLocation.x + (inLocation.x - outLocation.x) * 0.5 - ), - y: outLocation.y + midY, - }; - - const midB = { - x: Math.min( - inLocation.x, - inLocation.x - (inLocation.x - outLocation.x) * 0.5 - ), - y: outLocation.y + midY, - }; - - const pivotB = { - x: - inLocation.x - Math.max(padding, (inLocation.x - outLocation.x) * 0.25), - y: outLocation.y + midY + (inLocation.y - (outLocation.y + midY)) * 0.5, - }; - - // Next calculate the control points. - const angleA = Math.atan2(midA.y - outLocation.y, midA.x - outLocation.x); - const angleB = angleA + Math.PI; - const dx = Math.abs(pivotA.x - outLocation.x); - const dy = Math.abs(pivotA.y - outLocation.y); - const distance = Math.min(dy, Math.sqrt(dx * dx + dy * dy)); - - const cpA1 = { - x: pivotA.x - Math.cos(angleA) * distance, - y: pivotA.y - Math.sin(angleA) * distance, - }; - - const cpA2 = { - x: pivotA.x + Math.cos(angleA) * distance, - y: pivotA.y + Math.sin(angleA) * distance, - }; - - const cpB1 = { - x: pivotB.x + Math.cos(angleB) * distance, - y: pivotB.y + Math.sin(angleB) * distance, - }; - - const cpB2 = { - x: pivotB.x - Math.cos(angleB) * distance, - y: pivotB.y - Math.sin(angleB) * distance, - }; - - // Lines. - this.#edgeGraphic.beginPath(); - this.#edgeGraphic.moveTo(outLocation.x, outLocation.y); - if (Math.abs(midA.x - midB.x) > 0.5) { - this.#edgeGraphic.bezierCurveTo( - cpA1.x, - cpA1.y, - cpA2.x, - cpA2.y, - midA.x, - midA.y - ); - this.#edgeGraphic.lineTo(midB.x, midB.y); - this.#edgeGraphic.bezierCurveTo( - cpB1.x, - cpB1.y, - cpB2.x, - cpB2.y, - inLocation.x, - inLocation.y - ); - } else { - this.#edgeGraphic.quadraticCurveTo( - pivotA.x, - outLocation.y, - midA.x, - midA.y - ); - this.#edgeGraphic.quadraticCurveTo( - pivotB.x, - inLocation.y, - inLocation.x, - inLocation.y - ); - } - this.#edgeGraphic.stroke(); - this.#edgeGraphic.closePath(); - - // Circles at the start & end. - this.#edgeGraphic.beginPath(); - this.#edgeGraphic.circle(outLocation.x, outLocation.y, 2); - this.#edgeGraphic.circle(inLocation.x, inLocation.y, 2); - this.#edgeGraphic.closePath(); - this.#edgeGraphic.fill({ color: edgeColor }); - - // Hit Area. - if (Math.abs(midA.x - midB.x) > 0.5) { - const hitAreaSpacingX = - this.#hitAreaSpacing * (outLocation.y < inLocation.y ? 1 : -1); - const hitAreaSpacingY = this.#hitAreaSpacing; - - this.#edgeGraphic.hitArea = new PIXI.Polygon([ - outLocation.x, - outLocation.y - hitAreaSpacingY, - - ...calculatePointsOnCubicBezierCurve( - outLocation.x, - outLocation.y - hitAreaSpacingY, - cpA1.x + hitAreaSpacingX, - cpA1.y, - cpA2.x + hitAreaSpacingX, - cpA2.y, - midA.x, - midA.y + hitAreaSpacingY, - 0.0, - 1, - 0.1 - ), - - midA.x, - midA.y + hitAreaSpacingY, - - midB.x, - midB.y + hitAreaSpacingY, - - ...calculatePointsOnCubicBezierCurve( - midB.x, - midB.y + hitAreaSpacingY, - cpB1.x + hitAreaSpacingX, - cpB1.y, - cpB2.x + hitAreaSpacingX, - cpB2.y, - inLocation.x, - inLocation.y - hitAreaSpacingY, - 0.0, - 1, - 0.1 - ), - - inLocation.x, - inLocation.y + hitAreaSpacingY, - - ...calculatePointsOnCubicBezierCurve( - inLocation.x, - inLocation.y + hitAreaSpacingY, - cpB2.x - hitAreaSpacingX, - cpB2.y, - cpB1.x - hitAreaSpacingX, - cpB1.y, - midB.x, - midB.y - hitAreaSpacingY, - 0.0, - 1, - 0.1 - ), - - midA.x, - midA.y - hitAreaSpacingY, - - ...calculatePointsOnCubicBezierCurve( - midA.x, - midA.y - hitAreaSpacingY, - cpA2.x - hitAreaSpacingX, - cpA2.y, - cpA1.x - hitAreaSpacingX, - cpA1.y, - outLocation.x, - outLocation.y + hitAreaSpacingY, - 0.0, - 1, - 0.1 - ), - ]); - } else { - const angle = Math.atan2( - inLocation.y - outLocation.y, - inLocation.x - outLocation.x - ); - const xDist = Math.sin(angle) * this.#hitAreaSpacing; - const yDist = Math.cos(angle) * this.#hitAreaSpacing; - - this.#edgeGraphic.hitArea = new PIXI.Polygon([ - outLocation.x, - outLocation.y - this.#hitAreaSpacing, - - ...calculatePointsOnQuadraticBezierCurve( - // Start - outLocation.x, - outLocation.y - this.#hitAreaSpacing, - - // Control - pivotA.x + xDist, - outLocation.y - this.#hitAreaSpacing, - - // End - midA.x + xDist, - midA.y - yDist, - - 0.2, - 0.8, - 0.1 - ), - - ...calculatePointsOnQuadraticBezierCurve( - // Start - midA.x + xDist, - midA.y - yDist, - - // Control - pivotB.x + xDist, - inLocation.y - this.#hitAreaSpacing, - - // End - inLocation.x, - inLocation.y - this.#hitAreaSpacing, - - 0.2, - 0.8, - 0.1 - ), - - inLocation.x, - inLocation.y - this.#hitAreaSpacing, - - inLocation.x, - inLocation.y + this.#hitAreaSpacing, - - ...calculatePointsOnQuadraticBezierCurve( - // Start - inLocation.x, - inLocation.y + this.#hitAreaSpacing, - - // Control - pivotB.x - xDist, - inLocation.y + this.#hitAreaSpacing, - - // End - midA.x - xDist, - midA.y + yDist, - - 0.2, - 0.8, - 0.1 - ), - - ...calculatePointsOnQuadraticBezierCurve( - // Start - midA.x - xDist, - midA.y + yDist, - - // Control - pivotA.x - xDist, - outLocation.y + this.#hitAreaSpacing, - - // End - outLocation.x, - outLocation.y + this.#hitAreaSpacing, - - 0.2, - 0.8, - 0.1 - ), - - outLocation.x, - outLocation.y + this.#hitAreaSpacing, - ]); - } - - if (this.value && this.value.length) { - const x = outLocation.x + (inLocation.x - outLocation.x) * 0.5; - const y = outLocation.y + (inLocation.y - outLocation.y) * 0.5; - this.#valueSelector.visible = true; - this.#valueSelector.x = x; - this.#valueSelector.y = y; - - if (this.#valueSprite) { - this.#valueSprite.x = x - 8; - this.#valueSprite.y = y - 8; - this.#valueSprite.visible = true; - } - } else { - this.#valueSelector.visible = false; - if (this.#valueSprite) { - this.#valueSprite.visible = false; - } - } - } -} diff --git a/packages/shared-ui/src/elements/editor/graph-node-activity-marker.ts b/packages/shared-ui/src/elements/editor/graph-node-activity-marker.ts deleted file mode 100644 index 73eaf5119ac..00000000000 --- a/packages/shared-ui/src/elements/editor/graph-node-activity-marker.ts +++ /dev/null @@ -1,176 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as PIXI from "pixi.js"; -import { getGlobalColor } from "./utils"; -import { GRAPH_OPERATIONS } from "./types"; -import { ComponentActivityItem } from "../../types/types"; - -const inputColor = getGlobalColor("--bb-inputs-400"); -const nodeColor = getGlobalColor("--bb-nodes-400"); -const outputColor = getGlobalColor("--bb-boards-500"); -const errorColor = getGlobalColor("--bb-warning-600"); -const neutralColor = getGlobalColor("--bb-neutral-400"); -const textColor = getGlobalColor("--bb-neutral-0"); - -export class GraphNodeActivityMarker extends PIXI.Container { - #isDirty = false; - #background = new PIXI.Graphics(); - - #radius = 4; - #paddingVertical = 4; - #paddingHorizonal = 8; - #textSize = 12; - #type = ""; - #color = 0; - #activity: ComponentActivityItem[] | null = null; - - #label = new PIXI.Text({ - text: "0", - style: { - fontFamily: "Arial", - fontSize: this.#textSize, - fill: textColor, - align: "center", - textBaseline: "bottom", - whiteSpace: "pre", - }, - }); - - constructor() { - super(); - - this.#background.cursor = "pointer"; - this.#background.eventMode = "static"; - this.#label.eventMode = "none"; - - this.addChild(this.#background); - this.addChild(this.#label); - - this.#label.x = this.#paddingHorizonal; - this.#label.y = this.#paddingVertical; - - this.visible = false; - - this.onRender = () => { - if (!this.#isDirty) { - return; - } - - this.#isDirty = false; - this.#draw(); - }; - - this.addListener("pointerover", (evt: PIXI.FederatedPointerEvent) => { - const message = "Click for component activity"; - const x = evt.clientX; - const y = evt.clientY; - - this.emit(GRAPH_OPERATIONS.GRAPH_SHOW_TOOLTIP, message, x, y); - }); - - this.addListener("pointerout", () => { - this.emit(GRAPH_OPERATIONS.GRAPH_HIDE_TOOLTIP); - }); - - this.addEventListener("click", () => { - if (!this.#activity) { - return; - } - - const newestActivity = this.#activity[this.#activity.length - 1]; - if (!newestActivity) { - return; - } - - this.emit( - GRAPH_OPERATIONS.GRAPH_NODE_ACTIVITY_SELECTED, - getRunId(newestActivity.path) - ); - }); - } - - get dimensions() { - return { - width: this.#label.width + 2 * this.#paddingHorizonal, - height: this.#label.height + 2 * this.#paddingVertical, - }; - } - - get type() { - return this.#type; - } - - set type(type: string) { - this.#type = type; - this.#isDirty = true; - } - - get activity() { - return this.#activity; - } - - set activity(activity: ComponentActivityItem[] | null) { - this.#activity = activity; - - if (!activity || !activity.length) { - this.visible = false; - return; - } - - this.visible = true; - const newestActivity = activity[activity.length - 1]; - - if (this.#label.text !== activity.length.toString()) { - this.#label.text = activity.length; - } - - switch (newestActivity.type) { - case "input": - this.#color = inputColor; - break; - - case "output": - this.#color = outputColor; - break; - - case "error": - this.#color = errorColor; - break; - - default: - this.#color = nodeColor; - break; - } - - // TODO: Decide if individual colors is helpful. - if (newestActivity.type === "error") { - this.#color = errorColor; - } else { - this.#color = neutralColor; - } - this.#isDirty = true; - } - - #draw() { - this.#background.clear(); - - this.#background.beginPath(); - this.#background.roundRect( - 0, - 0, - this.#label.width + 2 * this.#paddingHorizonal, - this.#label.height + 2 * this.#paddingVertical, - this.#radius - ); - this.#background.closePath(); - this.#background.fill({ color: this.#color }); - } -} - -function getRunId(path: number[]) { - return `e-${path.slice(0, -1).join(".")}`; -} diff --git a/packages/shared-ui/src/elements/editor/graph-node-footer.ts b/packages/shared-ui/src/elements/editor/graph-node-footer.ts deleted file mode 100644 index c5f59eee771..00000000000 --- a/packages/shared-ui/src/elements/editor/graph-node-footer.ts +++ /dev/null @@ -1,163 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { InspectablePort, PortStatus } from "@google-labs/breadboard"; -import * as PIXI from "pixi.js"; -import { getGlobalColor, isConfigurablePort } from "./utils"; -import { GraphNodePort } from "./graph-node-port"; -import { GRAPH_OPERATIONS, GraphNodePortType } from "./types"; - -const portTextColor = getGlobalColor("--bb-neutral-900"); - -export class GraphNodeFooter extends PIXI.Container { - #width = 300; - #height = 40; - #textSize = 12; - #portTextColor = portTextColor; - #padding = 12; - #itemPadding = 16; - #spacing = 4; - #inPorts: InspectablePort[] | null = null; - #inPortsData: Map< - string, - { port: InspectablePort; label: PIXI.Text; nodePort: GraphNodePort } | null - > = new Map(); - - readOnly = false; - - get empty() { - return this.#inPortsData.size === 0; - } - - set inPorts(ports: InspectablePort[] | null) { - this.#inPorts = ports; - this.#width = 0; - - if (!ports) { - return; - } - - this.#width = this.#padding; - - for (const port of ports) { - if (!isConfigurablePort(port)) { - continue; - } - - if (port.status !== PortStatus.Missing && port.value === undefined) { - continue; - } - - let portItem = this.#inPortsData.get(port.name); - if (!portItem) { - const label = new PIXI.Text({ - text: port.title, - style: { - fontFamily: "Arial", - fontSize: this.#textSize, - fill: this.#portTextColor, - align: "left", - }, - }); - - const nodePort = new GraphNodePort(GraphNodePortType.INERT); - - this.addChild(label); - this.addChild(nodePort); - - portItem = { label, port, nodePort }; - this.#inPortsData.set(port.name, portItem); - } - - if (portItem.label.text !== port.title) { - portItem.label.text = port.title; - } - - portItem.port = port; - portItem.nodePort.status = port.status; - portItem.nodePort.configured = port.configured; - - portItem.nodePort.x = this.#width; - portItem.nodePort.y = this.#height * 0.5; - - portItem.label.x = - portItem.nodePort.x + portItem.nodePort.radius * 2 + this.#spacing; - portItem.label.y = (this.#height - portItem.label.height) * 0.5; - - this.#width += - portItem.nodePort.radius * 2 + - this.#spacing + - portItem.label.width + - this.#itemPadding; - - // Now that all the render-centric stuff is set up, check the read-only - // state to determine if click handlers etc should be added. - portItem.label.removeAllListeners(); - if (this.readOnly) { - return; - } - - portItem.label.alpha = 0.65; - portItem.label.cursor = "pointer"; - - portItem.label.addEventListener( - "click", - (evt: PIXI.FederatedPointerEvent) => { - this.emit( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_VALUE_EDIT, - portItem.port, - evt.clientX, - evt.clientY - ); - } - ); - - portItem.label.addEventListener("pointerover", (evt) => { - const ptrEvent = evt.nativeEvent as PointerEvent; - const [top] = ptrEvent.composedPath(); - if (!(top instanceof HTMLElement)) { - return; - } - - if (top.tagName !== "CANVAS") { - return; - } - portItem.label.alpha = 1; - }); - - portItem.label.addEventListener("pointerout", () => { - portItem.label.alpha = 0.65; - }); - } - - for (const [inPortName, portItem] of this.#inPortsData) { - const port = ports.find((inPort) => inPort.name === inPortName); - if (!port) { - continue; - } - - // Unless the port is missing a value, we can remove it when it has - // no value set. - if (port.status !== PortStatus.Missing && port.value === undefined) { - portItem?.label.removeFromParent(); - portItem?.label.destroy(); - - portItem?.nodePort.removeFromParent(); - portItem?.nodePort.destroy(); - - this.#inPortsData.delete(inPortName); - } - } - } - - get inPorts() { - return this.#inPorts; - } - - get dimensions() { - return { width: this.#width, height: this.#height }; - } -} diff --git a/packages/shared-ui/src/elements/editor/graph-node-port.ts b/packages/shared-ui/src/elements/editor/graph-node-port.ts deleted file mode 100644 index 4111f46ca67..00000000000 --- a/packages/shared-ui/src/elements/editor/graph-node-port.ts +++ /dev/null @@ -1,158 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as PIXI from "pixi.js"; -import { GraphNodePortType } from "./types.js"; -import { PortStatus } from "@google-labs/breadboard"; -import { getGlobalColor } from "./utils.js"; - -const connectedColor = getGlobalColor("--bb-inputs-200"); -const danglingColor = getGlobalColor("--bb-warning-300"); -const indeterminateColor = getGlobalColor("--bb-neutral-300"); -const missingColor = getGlobalColor("--bb-warning-200"); -const readyColor = getGlobalColor("--bb-neutral-200"); -const configuredColor = getGlobalColor("--bb-ui-300"); - -const connectedBorderColor = getGlobalColor("--bb-inputs-600"); -const danglingBorderColor = getGlobalColor("--bb-warning-700"); -const indeterminateBorderColor = getGlobalColor("--bb-neutral-700"); -const missingBorderColor = getGlobalColor("--bb-warning-600"); -const readyBorderColor = getGlobalColor("--bb-neutral-600"); -const configuredBorderColor = getGlobalColor("--bb-ui-600"); - -export class GraphNodePort extends PIXI.Graphics { - #isDirty = true; - #radius = 4; - #status: PortStatus = PortStatus.Indeterminate; - #configured = false; - #colors: { [K in PortStatus]: number } & { configured: number } = { - [PortStatus.Connected]: connectedColor, - [PortStatus.Dangling]: danglingColor, - [PortStatus.Indeterminate]: indeterminateColor, - [PortStatus.Missing]: missingColor, - [PortStatus.Ready]: readyColor, - configured: configuredColor, - }; - #borderColors: { [K in PortStatus]: number } & { configured: number } = { - [PortStatus.Connected]: connectedBorderColor, - [PortStatus.Dangling]: danglingBorderColor, - [PortStatus.Indeterminate]: indeterminateBorderColor, - [PortStatus.Missing]: missingBorderColor, - [PortStatus.Ready]: readyBorderColor, - configured: configuredBorderColor, - }; - #overrideStatus: PortStatus | null = null; - #readOnly = false; - - constructor(public type: GraphNodePortType) { - super(); - - this.onRender = () => { - if (!this.#isDirty) { - return; - } - this.#isDirty = false; - this.clear(); - this.#draw(); - }; - } - - set readOnly(readOnly: boolean) { - if (readOnly === this.#readOnly) { - return; - } - - this.#readOnly = readOnly; - this.#isDirty = true; - } - - get readOnly() { - return this.#readOnly; - } - - set radius(radius: number) { - if (radius === this.#radius) { - return; - } - - this.#radius = radius; - this.#isDirty = true; - } - - get radius() { - return this.#radius; - } - - set configured(configured: boolean) { - if (configured === this.#configured) { - return; - } - - this.#configured = configured; - this.#isDirty = true; - } - - get configured() { - return this.#configured; - } - - set overrideStatus(overrideStatus: PortStatus | null) { - if (overrideStatus === this.#overrideStatus) { - return; - } - - this.#overrideStatus = overrideStatus; - this.#isDirty = true; - } - - get overrideStatus() { - return this.#overrideStatus; - } - - set status(status: PortStatus) { - if (status === this.#status) { - return; - } - - this.#status = status; - this.#isDirty = true; - } - - get status() { - return this.#status; - } - - #draw() { - // Adjust the hit area so it's a bit bigger. - this.hitArea = new PIXI.Rectangle( - -this.#radius * 2, - -this.#radius * 2, - this.#radius * 4, - this.#radius * 4 - ); - - const status = this.#overrideStatus ?? this.#status; - this.setStrokeStyle({ - color: this.#configured - ? this.#borderColors["configured"] - : this.#borderColors[status], - width: 1, - }); - - this.beginPath(); - this.circle(0, 0, this.#radius); - this.fill({ - color: this.#configured - ? this.#colors["configured"] - : this.#colors[status], - }); - this.stroke(); - this.closePath(); - - this.eventMode = "static"; - this.cursor = this.#readOnly ? undefined : "pointer"; - } -} diff --git a/packages/shared-ui/src/elements/editor/graph-node.ts b/packages/shared-ui/src/elements/editor/graph-node.ts deleted file mode 100644 index 3012ba8ee7f..00000000000 --- a/packages/shared-ui/src/elements/editor/graph-node.ts +++ /dev/null @@ -1,1180 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { InspectablePort, PortStatus } from "@google-labs/breadboard"; -import * as PIXI from "pixi.js"; -import { - ComponentExpansionState, - GRAPH_OPERATIONS, - GraphNodePortType, -} from "./types.js"; -import { GraphNodePort } from "./graph-node-port.js"; -import { GraphOverflowMenu } from "./graph-overflow-menu.js"; -import { GraphAssets } from "./graph-assets.js"; -import { - computeNextExpansionState, - DBL_CLICK_DELTA, - getGlobalColor, -} from "./utils.js"; -import { GraphNodeFooter } from "./graph-node-footer.js"; -import { GraphPortLabel as GraphNodePortLabel } from "./graph-port-label.js"; -import { GraphNodeActivityMarker } from "./graph-node-activity-marker.js"; -import { ComponentActivityItem } from "../../types/types.js"; - -const borderColor = getGlobalColor("--bb-neutral-500"); -const nodeTextColor = getGlobalColor("--bb-neutral-900"); -const segmentDividerColor = getGlobalColor("--bb-neutral-300"); - -const selectedNodeColor = getGlobalColor("--bb-ui-600"); -const highlightForAdHocNodeColor = getGlobalColor("--bb-boards-500"); - -const ICON_SCALE = 0.42; - -export class GraphNode extends PIXI.Container { - #width = 0; - #height = 0; - - #isDirty = true; - #id = ""; - #type = ""; - #title = ""; - #titleText: PIXI.Text | null = null; - #typeTitle: string; - #borderRadius = 8; - #color = nodeTextColor; - - #titleTextColor = nodeTextColor; - #titleTextSize = 14; - - #portTextColor = nodeTextColor; - #borderColor = borderColor; - #segmentDividerColor = segmentDividerColor; - #selectedColor = selectedNodeColor; - #highlightForAdHocColor = highlightForAdHocNodeColor; - #textSize = 12; - #backgroundColor = 0x333333; - #padding = 12; - #activityPadding = 20; - #menuPadding = 8; - #iconPadding = 8; - #portLabelVerticalPadding = 4; - #portLabelHorizontalPadding = 20; - #portPadding = 8; - #portRadius = 4; - #background = new PIXI.Graphics(); - #footer = new GraphNodeFooter(); - #activityMarker = new GraphNodeActivityMarker(); - #inPorts: InspectablePort[] | null = null; - #inPortsData: Map< - string, - { - port: InspectablePort; - label: GraphNodePortLabel; - nodePort: GraphNodePort; - } | null - > = new Map(); - #inPortsSortedByName: Array<{ - port: InspectablePort; - label: GraphNodePortLabel; - nodePort: GraphNodePort; - }> = []; - #outPorts: InspectablePort[] | null = null; - #outPortsData: Map< - string, - { port: InspectablePort; label: PIXI.Text; nodePort: GraphNodePort } | null - > = new Map(); - #outPortsSortedByName: Array<{ - port: InspectablePort; - label: PIXI.Text; - nodePort: GraphNodePort; - }> = []; - #inPortLocations: Map = new Map(); - #outPortLocations: Map = new Map(); - #selected = false; - #highlightForAdHoc = false; - #expansionState: ComponentExpansionState = "expanded"; - #emitCollapseToggleEventOnNextDraw = false; - - #showNodePreviewValues = false; - #showNodeTypeDescriptions = false; - #overflowMenu = new GraphOverflowMenu(); - #headerInPort = new GraphNodePort(GraphNodePortType.IN); - #headerOutPort = new GraphNodePort(GraphNodePortType.OUT); - #lastClickTime = 0; - #icon: string | null = null; - #iconSprite: PIXI.Sprite | null = null; - #activity: ComponentActivityItem[] | null = null; - - readOnly = false; - - constructor( - id: string, - type: string, - title: string, - typeTitle: string, - public fixedInputs = true, - public fixedOutputs = true - ) { - super(); - - this.title = title; - this.id = id; - this.type = type; - this.#typeTitle = typeTitle; - - this.backgroundColor = 0xffffff; - this.portTextColor = nodeTextColor; - - this.eventMode = "static"; - - this.#background.eventMode = "auto"; - this.addChild(this.#background); - this.addChild(this.#headerInPort); - this.addChild(this.#headerOutPort); - this.addChild(this.#footer); - this.addChild(this.#activityMarker); - - this.#headerInPort.label = "_header-port-in"; - this.#headerOutPort.label = "_header-port-out"; - this.#headerInPort.visible = false; - this.#headerOutPort.visible = false; - - this.#overflowMenu.on( - GRAPH_OPERATIONS.GRAPH_NODE_MENU_CLICKED, - (location: PIXI.ObservablePoint) => { - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_MENU_REQUESTED, this, location); - } - ); - - this.#activityMarker.on( - GRAPH_OPERATIONS.GRAPH_NODE_ACTIVITY_SELECTED, - (...args: unknown[]) => { - this.emit( - GRAPH_OPERATIONS.GRAPH_NODE_ACTIVITY_SELECTED, - this.title, - ...args - ); - } - ); - - this.#activityMarker.on( - GRAPH_OPERATIONS.GRAPH_SHOW_TOOLTIP, - (...args: unknown[]) => { - this.emit(GRAPH_OPERATIONS.GRAPH_SHOW_TOOLTIP, ...args); - } - ); - - this.#activityMarker.on( - GRAPH_OPERATIONS.GRAPH_HIDE_TOOLTIP, - (...args: unknown[]) => { - this.emit(GRAPH_OPERATIONS.GRAPH_HIDE_TOOLTIP, ...args); - } - ); - - this.#footer.on( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_VALUE_EDIT, - (...args: unknown[]) => { - // Propagate to the parent graph. - this.emit( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_VALUE_EDIT, - this.label, - ...args - ); - } - ); - - this.onRender = () => { - if (this.#isDirty) { - this.#isDirty = false; - this.#draw(); - - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_DRAWN); - } - - if (this.#emitCollapseToggleEventOnNextDraw) { - this.#emitCollapseToggleEventOnNextDraw = false; - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_EXPAND_COLLAPSE); - } - }; - } - - addPointerEventListeners() { - let dragStart: PIXI.PointData | null = null; - let originalPosition: PIXI.ObservablePoint | null = null; - let hasMoved = false; - - this.addEventListener("click", (evt: PIXI.FederatedPointerEvent) => { - const clickDelta = window.performance.now() - this.#lastClickTime; - this.#lastClickTime = window.performance.now(); - - if (clickDelta > DBL_CLICK_DELTA) { - return; - } - - if (!this.#titleText) { - return; - } - - const titleHeight = - this.#padding + this.#titleText.height + this.#padding; - - const nodeGlobal = this.getBounds(); - const titleY = this.toGlobal({ x: 0, y: titleHeight }).y; - - const isInHeaderArea = - evt.global.x > nodeGlobal.left && - evt.global.x < nodeGlobal.right && - evt.global.y > nodeGlobal.top && - evt.global.y < titleY; - - if (!isInHeaderArea) { - return; - } - - this.expansionState = computeNextExpansionState(this.expansionState); - this.#lastClickTime = 0; - }); - - this.addEventListener("pointerover", () => { - this.cursor = "pointer"; - }); - - this.addEventListener("pointerdown", (evt: PIXI.FederatedPointerEvent) => { - if (!(evt.target instanceof GraphNode) || !evt.isPrimary) { - return; - } - - hasMoved = false; - dragStart = evt.global.clone(); - originalPosition = this.position.clone(); - }); - - this.addEventListener( - "globalpointermove", - (evt: PIXI.FederatedPointerEvent) => { - if (!dragStart || !originalPosition || !evt.isPrimary) { - return; - } - - const scale = this.worldTransform.a; - const dragPosition = evt.global; - const dragDeltaX = (dragPosition.x - dragStart.x) / scale; - const dragDeltaY = (dragPosition.y - dragStart.y) / scale; - - this.x = Math.round(originalPosition.x + dragDeltaX); - this.y = Math.round(originalPosition.y + dragDeltaY); - hasMoved = true; - - this.cursor = "grabbing"; - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_MOVED, this.x, this.y, false); - } - ); - - const onPointerUp = () => { - dragStart = null; - originalPosition = null; - if (!hasMoved) { - return; - } - - hasMoved = false; - this.cursor = "pointer"; - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_MOVED, this.x, this.y, true); - }; - - this.addEventListener("pointerupoutside", onPointerUp); - this.addEventListener("pointerup", onPointerUp); - } - - get id() { - return this.#id; - } - - set id(id: string) { - this.#id = id; - } - - get title() { - return this.#title; - } - - set title(title: string) { - this.#title = title; - this.#isDirty = true; - } - - get borderColor() { - return this.#borderColor; - } - - set borderColor(borderColor: number) { - this.#borderColor = borderColor; - this.#isDirty = true; - } - - get icon() { - return this.#icon; - } - - set icon(icon: string | null) { - this.#icon = icon; - if (icon) { - if (!this.#iconSprite) { - const texture = GraphAssets.instance().get(icon); - this.#iconSprite = texture ? new PIXI.Sprite(texture) : null; - - if (this.#iconSprite) { - this.#iconSprite.scale.x = ICON_SCALE; - this.#iconSprite.scale.y = ICON_SCALE; - } - } - } else { - this.#iconSprite = null; - } - - this.#isDirty = true; - } - - set showNodePreviewValues(showNodePreviewValues: boolean) { - if (this.#showNodePreviewValues === showNodePreviewValues) { - return; - } - - this.#showNodePreviewValues = showNodePreviewValues; - this.#isDirty = true; - } - - get showNodePreviewValues() { - return this.#showNodePreviewValues; - } - - set showNodeTypeDescriptions(showNodeTypeDescriptions: boolean) { - if (this.#showNodeTypeDescriptions === showNodeTypeDescriptions) { - return; - } - - this.#showNodeTypeDescriptions = showNodeTypeDescriptions; - this.#isDirty = true; - } - - get showNodeTypeDescriptions() { - return this.#showNodeTypeDescriptions; - } - - get selected() { - return this.#selected; - } - - set selected(selected: boolean) { - this.#selected = selected; - this.#isDirty = true; - } - - get highlightForAdHoc() { - return this.#highlightForAdHoc; - } - - set highlightForAdHoc(highlightForAdHoc: boolean) { - if (this.fixedInputs && this.fixedOutputs) { - return; - } - - this.#highlightForAdHoc = highlightForAdHoc; - this.#isDirty = true; - } - - get expansionState() { - return this.#expansionState; - } - - set expansionState(state: ComponentExpansionState) { - this.#expansionState = state; - this.#emitCollapseToggleEventOnNextDraw = true; - this.#isDirty = true; - for (const child of this.children) { - if (child instanceof GraphNodePortLabel) { - child.expansionState = state; - } - } - } - - get collapsed() { - return this.#expansionState === "collapsed"; - } - - get type() { - return this.#type; - } - - set type(type: string) { - this.#type = type; - this.#isDirty = true; - } - - set borderRadius(borderRadius: number) { - this.#borderRadius = borderRadius; - this.#isDirty = true; - } - - get borderRadius() { - return this.#borderRadius; - } - - set color(color: number) { - this.#color = color; - this.#isDirty = true; - } - - get color() { - return this.#color; - } - - set activity(activity: ComponentActivityItem[] | null) { - this.#activity = activity; - this.#activityMarker.activity = this.#activity; - - this.#isDirty = true; - } - - get activity() { - return this.#activity; - } - - set titleTextColor(titleTextColor: number) { - this.#titleTextColor = titleTextColor; - this.#isDirty = true; - } - - get titleTextColor() { - return this.#titleTextColor; - } - - set portTextColor(portTextColor: number) { - this.#portTextColor = portTextColor; - this.#isDirty = true; - } - - get portTextColor() { - return this.#portTextColor; - } - - set textSize(textSize: number) { - this.#textSize = textSize; - this.#isDirty = true; - } - - get textSize() { - return this.#textSize; - } - - set backgroundColor(backgroundColor: number) { - this.#backgroundColor = backgroundColor; - this.#isDirty = true; - } - - get backgroundColor() { - return this.#backgroundColor; - } - - set padding(padding: number) { - this.#padding = padding; - this.#isDirty = true; - } - - get padding() { - return this.#padding; - } - - set portLabelVerticalPadding(portLabelVerticalPadding: number) { - this.#portLabelVerticalPadding = portLabelVerticalPadding; - this.#isDirty = true; - } - - get portLabelVerticalPadding() { - return this.#portLabelVerticalPadding; - } - - get dimensions() { - return { width: this.#width, height: this.#height }; - } - - set inPorts(ports: InspectablePort[] | null) { - this.#footer.readOnly = this.readOnly; - this.#footer.inPorts = ports; - this.#inPorts = ports; - this.#isDirty = true; - if (!ports) { - return; - } - - for (const port of ports) { - let portItem = this.#inPortsData.get(port.name); - if (!portItem) { - const label = new GraphNodePortLabel(port, this.#showNodePreviewValues); - label.expansionState = this.#expansionState; - label.on( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_VALUE_EDIT, - (...args: unknown[]) => { - // Propagate to the parent graph. - this.emit( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_VALUE_EDIT, - this.label, - ...args - ); - } - ); - - this.addChild(label); - label.visible = false; - - const nodePort = new GraphNodePort(GraphNodePortType.IN); - this.addChild(nodePort); - nodePort.visible = false; - - portItem = { label, port, nodePort }; - this.#inPortsData.set(port.name, portItem); - - nodePort.addEventListener("mouseover", (event) => { - this.emit( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_MOUSEENTER, - // Port objects can change! The local `port` variable we have might - // get out of date, so we need to grab the latest version. (This - // pattern repeated a few times below). - this.#inPortsData.get(port.name)?.port, - event.client - ); - }); - - nodePort.addEventListener("mouseleave", (event) => { - this.emit( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_MOUSELEAVE, - this.#inPortsData.get(port.name)?.port, - event.client - ); - }); - } - - portItem.label.readOnly = this.readOnly; - portItem.label.showNodePreviewValues = this.showNodePreviewValues; - portItem.label.port = port; - portItem.port = port; - portItem.nodePort.readOnly = this.readOnly; - } - - for (const [inPortName, portItem] of this.#inPortsData) { - if (!ports.find((inPort) => inPort.name === inPortName)) { - portItem?.label.removeFromParent(); - portItem?.label.destroy(); - - portItem?.nodePort.removeFromParent(); - portItem?.nodePort.destroy(); - - this.#inPortsData.delete(inPortName); - } - } - - this.#inPortsSortedByName.length = 0; - for (const portItem of this.#inPortsData.values()) { - if (!portItem) { - continue; - } - - this.#inPortsSortedByName.push(portItem); - } - - this.#inPortsSortedByName.sort((portA, portB) => { - // This is a bit of a gross hack to group items. - // If the port name has dashes, it should be sorted to the bottom. - // Enables grouping ports a bit. Just add dashes to the port names to - // put them into a separate group. - // TODO: Come up with a better way to group ports. - const portAHasDashes = portA.port.name.includes("-"); - const portBHasDashes = portB.port.name.includes("-"); - if (portAHasDashes && !portBHasDashes) { - return 1; - } - if (!portAHasDashes && portBHasDashes) { - return -1; - } - if (portA.label.text > portB.label.text) { - return 1; - } - - return -1; - }); - } - - get inPorts() { - return this.#inPorts; - } - - set outPorts(ports: InspectablePort[] | null) { - this.#outPorts = ports; - this.#isDirty = true; - if (!ports) { - return; - } - - for (const port of ports) { - let portItem = this.#outPortsData.get(port.name); - if (!portItem) { - const label = new PIXI.Text({ - text: port.title, - style: { - fontFamily: "Arial", - fontSize: this.#textSize, - fill: this.#portTextColor, - align: "right", - }, - }); - - this.addChild(label); - label.visible = false; - - const nodePort = new GraphNodePort(GraphNodePortType.OUT); - this.addChild(nodePort); - nodePort.visible = false; - - portItem = { label, port, nodePort }; - this.#outPortsData.set(port.name, portItem); - - nodePort.addEventListener("pointerover", (event) => { - this.emit( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_MOUSEENTER, - this.#outPortsData.get(port.name)?.port, - event.client - ); - }); - nodePort.addEventListener("pointerleave", (event) => { - this.emit( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_MOUSELEAVE, - this.#outPortsData.get(port.name)?.port, - event.client - ); - }); - } - - if (portItem.label.text !== port.title) { - portItem.label.text = port.title; - } - - portItem.port = port; - } - - for (const [outPortName, portItem] of this.#outPortsData) { - if (!ports.find((outPort) => outPort.name === outPortName)) { - portItem?.label.removeFromParent(); - portItem?.label.destroy(); - - portItem?.nodePort.removeFromParent(); - portItem?.nodePort.destroy(); - - this.#outPortsData.delete(outPortName); - } - } - - this.#outPortsSortedByName.length = 0; - for (const portItem of this.#outPortsData.values()) { - if (!portItem) { - continue; - } - - this.#outPortsSortedByName.push(portItem); - } - - this.#outPortsSortedByName.sort((portA, portB) => { - if (portA.label.text > portB.label.text) { - return 1; - } - - return -1; - }); - } - - get outPorts() { - return this.#outPorts; - } - - forceUpdateDimensions() { - this.#createTitleTextIfNeeded(); - this.#updateDimensions(); - this.#enforceEvenDimensions(); - } - - #createTitleTextIfNeeded() { - const nodeTitle = `${this.#title}${this.showNodeTypeDescriptions ? ` (${this.#typeTitle})` : ""}`; - if (this.#titleText) { - if (this.#titleText.text !== nodeTitle) { - this.#titleText.text = nodeTitle; - } - return; - } - - this.#titleText = new PIXI.Text({ - text: nodeTitle, - style: { - fontFamily: "Arial", - fontSize: this.#titleTextSize, - fill: this.#titleTextColor, - align: "left", - }, - }); - } - - /** - * Ensure that we have an even number of pixels just so we don't get fuzzy - * rendering on half pixels. - */ - #enforceEvenDimensions() { - if (this.#width % 2 === 1) { - this.#width++; - } - - if (this.#height % 2 === 1) { - this.#height++; - } - } - - #updateDimensions() { - const portCount = Math.max(this.#inPortsData.size, this.#outPortsData.size); - const footerEmpty = this.#footer.empty; - const footerDimensions = this.#footer.dimensions; - - // Height calculations. - let height = this.#padding + (this.#titleText?.height || 0) + this.#padding; - - // Only add the port heights on when the node is expanded. - if (this.collapsed && !footerEmpty) { - height += footerDimensions.height; - } - - // Width calculations. - let width = - this.#padding + - (this.#icon ? (this.#iconSprite?.width || 0) + this.#iconPadding : 0) + - (this.#titleText?.width || 0) + - this.#activityPadding + - this.#activityMarker.dimensions.width + - this.#menuPadding + - GraphOverflowMenu.width + - this.#menuPadding; - - const inPortLabels = Array.from(this.#inPortsData.values()); - const outPortLabels = Array.from(this.#outPortsData.values()); - - let maxInPortWidth = 0; - let inPortHeight = 0; - for (const inPort of inPortLabels) { - if (!inPort) { - continue; - } - - maxInPortWidth = Math.max(maxInPortWidth, inPort.label.dimensions.width); - if (this.collapsed || this.#shouldHidePort(inPort.port)) { - continue; - } - - inPortHeight += - this.#portLabelVerticalPadding + - inPort.label.dimensions.height + - this.#portLabelVerticalPadding; - } - - let maxOutPortWidth = 0; - let outPortHeight = 0; - for (const outPort of outPortLabels) { - if (!outPort) { - continue; - } - - maxOutPortWidth = Math.max(maxOutPortWidth, outPort.label.width); - if (this.collapsed || this.#shouldHidePort(outPort.port)) { - continue; - } - - outPortHeight += - this.#portLabelVerticalPadding + - outPort.label.height + - this.#portLabelVerticalPadding; - } - - width = Math.max( - width, - this.#padding + // Left hand side. - this.#portPadding + // Left hand port padding on right. - maxInPortWidth + // Left label at this row. - 2 * this.#portLabelHorizontalPadding + // Port label padding for both sides. - maxOutPortWidth + // Right label at this row. - this.#portPadding + // Right hand port padding on right. - this.#padding // Right hand side padding. - ); - - height += Math.max(inPortHeight, outPortHeight); - - if (!this.collapsed && portCount > 0) { - height += 2 * this.#padding; - } - - if (!footerEmpty && footerDimensions.width > width) { - width = footerDimensions.width; - } - - this.#width = width; - this.#height = height; - } - - #draw() { - this.forceUpdateDimensions(); - this.#drawBackground(); - const portStartY = this.#drawTitle(); - - if (this.collapsed) { - this.#hideAllPorts(); - this.#showHeaderPorts(); - } else { - this.#drawInPorts(portStartY); - this.#drawOutPorts(portStartY); - this.#hideHeaderPorts(); - } - this.#drawOverflowMenu(); - this.#drawActivityMarker(); - this.#drawFooterIfNeeded(); - } - - #drawActivityMarker() { - const titleHeight = - this.#padding + (this.#titleText?.height || 0) + this.#padding; - - const activityMarkerDimensions = this.#activityMarker.dimensions; - - this.#activityMarker.x = - this.#width - - this.#activityMarker.dimensions.width - - this.#menuPadding - - GraphOverflowMenu.width - - this.#menuPadding; - - this.#activityMarker.y = - (titleHeight - activityMarkerDimensions.height) * 0.5; - } - - #drawFooterIfNeeded() { - this.#footer.visible = this.collapsed; - this.#footer.y = this.#height - this.#footer.dimensions.height; - } - - #drawOverflowMenu() { - this.addChild(this.#overflowMenu); - - const titleHeight = - this.#padding + (this.#titleText?.height || 0) + this.#padding; - - this.#overflowMenu.x = - this.#width - this.#menuPadding - GraphOverflowMenu.width; - this.#overflowMenu.y = (titleHeight - GraphOverflowMenu.height) * 0.5; - } - - #showHeaderPorts() { - this.#headerInPort.visible = true; - this.#headerOutPort.visible = true; - - const titleHeight = - this.#padding + (this.#titleText?.height || 0) + this.#padding; - - this.#headerInPort.y = titleHeight / 2; - this.#headerOutPort.y = titleHeight / 2; - - this.#headerInPort.x = 0; - this.#headerOutPort.x = this.#width; - - let connectedInPorts = 0; - let inPortConfigured = false; - for (const inPort of this.#inPortsData.values()) { - if (!inPort) { - continue; - } - - if (inPort.port.status === PortStatus.Connected) { - connectedInPorts++; - } - - if (inPort.port.configured) { - inPortConfigured = true; - } - } - - if (connectedInPorts > 0) { - if (this.#headerInPort.status !== PortStatus.Connected) { - this.#headerInPort.status = PortStatus.Connected; - } - - if (connectedInPorts === 1) { - if (this.#headerInPort.configured !== inPortConfigured) { - this.#headerInPort.configured = inPortConfigured; - } - } else { - if (this.#headerInPort.configured) { - this.#headerInPort.configured = false; - } - } - } else { - if (this.#headerInPort.status !== PortStatus.Indeterminate) { - this.#headerInPort.status = PortStatus.Indeterminate; - } - } - - let connectedOutPorts = 0; - let outPortConfigured = false; - for (const outPort of this.#outPortsData.values()) { - if (!outPort) { - continue; - } - - if (outPort.port.status === PortStatus.Connected) { - connectedOutPorts++; - } - - if (outPort.port.configured) { - outPortConfigured = true; - } - } - - if (connectedOutPorts > 0) { - if (this.#headerOutPort.status !== PortStatus.Connected) { - this.#headerOutPort.status = PortStatus.Connected; - } - - if (connectedOutPorts === 1) { - if (this.#headerOutPort.configured !== outPortConfigured) { - this.#headerOutPort.configured = outPortConfigured; - } - } else { - if (this.#headerOutPort.configured) { - this.#headerOutPort.configured = false; - } - } - } else { - if (this.#headerOutPort.status !== PortStatus.Indeterminate) { - this.#headerOutPort.status = PortStatus.Indeterminate; - } - } - } - - #hideHeaderPorts() { - this.#headerInPort.visible = false; - this.#headerOutPort.visible = false; - } - - #hideAllPorts() { - for (const portItem of this.#inPortsData.values()) { - if (!portItem) { - continue; - } - - portItem.label.visible = false; - portItem.nodePort.visible = false; - } - - for (const portItem of this.#outPortsData.values()) { - if (!portItem) { - continue; - } - - portItem.label.visible = false; - portItem.nodePort.visible = false; - } - - this.#inPortLocations.clear(); - this.#outPortLocations.clear(); - } - - #drawBackground() { - // Toggling cacheAsBitmap back to false for the background seems to trip up - // PIXI, so instead we swap it out for a new Graphics instance, and we - // schedule its removal in the next frame. - if (this.#background) { - const existingBackground = this.#background; - existingBackground.removeFromParent(); - requestAnimationFrame(() => { - existingBackground.destroy(); - }); - - this.#background = new PIXI.Graphics(); - this.#background.eventMode = "auto"; - this.addChildAt(this.#background, 0); - } - - const borderSize = this.selected || this.#highlightForAdHoc ? 2 : 1; - this.#background.beginPath(); - this.#background.roundRect( - -borderSize, - -borderSize, - this.#width + 2 * borderSize, - this.#height + 2 * borderSize, - this.#borderRadius + borderSize - ); - this.#background.closePath(); - this.#background.fill({ - color: this.#highlightForAdHoc - ? this.#highlightForAdHocColor - : this.selected - ? this.#selectedColor - : this.#borderColor, - }); - - this.#background.beginPath(); - this.#background.roundRect( - 0, - 0, - this.#width, - this.#height, - this.#borderRadius - ); - this.#background.closePath(); - this.#background.fill({ color: this.#backgroundColor }); - - if (this.#titleText && !this.collapsed) { - const titleHeight = - this.#padding + this.#titleText.height + this.#padding; - this.#background.beginPath(); - this.#background.moveTo(0, titleHeight); - this.#background.lineTo(this.#width, titleHeight); - this.#background.closePath(); - this.#background.stroke({ color: this.#segmentDividerColor }); - } - - if (this.collapsed && !this.#footer.empty) { - const footerDimensions = this.#footer.dimensions; - const y = this.#height - footerDimensions.height; - this.#background.beginPath(); - this.#background.moveTo(0, y); - this.#background.lineTo(this.#width, y); - this.#background.closePath(); - this.#background.stroke({ color: this.#segmentDividerColor }); - } - } - - #drawTitle() { - const titleHeight = - this.#padding + (this.#titleText?.height || 0) + this.#padding; - - let titleStartX = this.#padding; - if (this.#iconSprite) { - this.#iconSprite.scale.x = ICON_SCALE; - this.#iconSprite.scale.y = ICON_SCALE; - this.#iconSprite.eventMode = "none"; - this.#iconSprite.x = titleStartX; - this.#iconSprite.y = (titleHeight - this.#iconSprite.height) / 2; - titleStartX += this.#iconSprite.width + this.#iconPadding; - this.addChild(this.#iconSprite); - } - - let portStartY = 0; - if (this.#titleText) { - this.#titleText.eventMode = "none"; - this.#titleText.x = titleStartX; - this.#titleText.y = this.#padding; - this.addChild(this.#titleText); - - // Move the labels a padding's distance from the bottom of the title. - portStartY += titleHeight + this.#padding; - } - - return portStartY; - } - - #drawInPorts(portStartY = 0) { - this.#inPortLocations.clear(); - - let portY = portStartY; - for (const portItem of this.#inPortsSortedByName) { - if (this.#shouldHidePort(portItem.port)) { - continue; - } - const { port, label, nodePort } = portItem; - nodePort.label = port.name; - nodePort.radius = this.#portRadius; - nodePort.x = 0; - nodePort.y = portY + this.#textSize * 0.5 + 0.5; - nodePort.overrideStatus = null; - nodePort.status = port.status; - nodePort.configured = port.configured && port.edges.length === 0; - nodePort.visible = true; - - this.#inPortLocations.set(port.name, nodePort.position); - - label.x = nodePort.x + this.#portRadius + this.#portPadding; - label.y = portY; - label.visible = true; - - portY += label.dimensions.height + 2 * this.#portLabelVerticalPadding; - } - } - - #drawOutPorts(portStartY = 0) { - this.#outPortLocations.clear(); - const portRowHeight = this.#textSize + 2 * this.#portLabelVerticalPadding; - - let portY = portStartY; - for (const portItem of this.#outPortsSortedByName) { - if (this.#shouldHidePort(portItem.port, "$error")) { - continue; - } - - const { port, label, nodePort } = portItem; - nodePort.label = port.name; - nodePort.radius = this.#portRadius; - nodePort.x = this.#width; - nodePort.y = portY + label.height * 0.5; - nodePort.overrideStatus = null; - nodePort.status = port.status; - nodePort.configured = port.configured && port.edges.length === 0; - nodePort.visible = true; - - this.#outPortLocations.set(port.name, nodePort.position); - - label.x = nodePort.x - this.#portRadius - this.#portPadding - label.width; - label.y = portY; - label.eventMode = "none"; - label.visible = true; - - portY += portRowHeight; - } - } - - inPortLocation(name: string): PIXI.ObservablePoint | null { - if (this.expansionState === "collapsed") { - return this.#headerInPort.position; - } - - return this.#inPortLocations.get(name) || null; - } - - outPortLocation(name: string): PIXI.ObservablePoint | null { - if (this.expansionState === "collapsed") { - return this.#headerOutPort.position; - } - - return this.#outPortLocations.get(name) || null; - } - - #shouldHidePort(port: InspectablePort | undefined, ...exclude: string[]) { - if (!port) return true; - if (this.expansionState === "advanced") { - return false; - } - if (port.status === PortStatus.Connected) { - return false; - } - if (port.star || port.name === "") { - return true; - } - if (exclude.includes(port.name)) { - return true; - } - return false; - } -} diff --git a/packages/shared-ui/src/elements/editor/graph-overflow-menu.ts b/packages/shared-ui/src/elements/editor/graph-overflow-menu.ts deleted file mode 100644 index 60f7056518c..00000000000 --- a/packages/shared-ui/src/elements/editor/graph-overflow-menu.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import * as PIXI from "pixi.js"; -import { GRAPH_OPERATIONS } from "./types.js"; -import { getGlobalColor } from "./utils.js"; - -const menuColor = getGlobalColor("--bb-neutral-600"); - -export class GraphOverflowMenu extends PIXI.Graphics { - #isDirty = true; - #radius = 1.5; - #gap = 2; - - static readonly width = 20; - static readonly height = 16; - - constructor() { - super(); - - this.hitArea = new PIXI.Rectangle( - 0, - 0, - GraphOverflowMenu.width, - GraphOverflowMenu.height - ); - - this.cursor = "pointer"; - this.eventMode = "static"; - - this.addEventListener("click", (evt: PIXI.FederatedPointerEvent) => { - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_MENU_CLICKED, evt.client); - }); - - this.onRender = () => { - if (!this.#isDirty) { - return; - } - this.clear(); - this.#draw(); - this.#isDirty = false; - }; - } - - #draw() { - const midX = GraphOverflowMenu.width / 2; - const midY = GraphOverflowMenu.height / 2; - - this.beginPath(); - this.circle(midX, midY - this.#gap - 2 * this.#radius, this.#radius); - this.circle(midX, midY, this.#radius); - this.circle(midX, midY + this.#gap + 2 * this.#radius, this.#radius); - this.fill({ color: menuColor }); - this.closePath(); - } -} diff --git a/packages/shared-ui/src/elements/editor/graph-port-label.ts b/packages/shared-ui/src/elements/editor/graph-port-label.ts deleted file mode 100644 index cc39f15371e..00000000000 --- a/packages/shared-ui/src/elements/editor/graph-port-label.ts +++ /dev/null @@ -1,329 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - InspectablePort, - isInlineData, - isLLMContent, - isLLMContentArray, - isStoredData, - isTextCapabilityPart, - PortStatus, -} from "@google-labs/breadboard"; -import * as PIXI from "pixi.js"; -import { getGlobalColor, isConfigurablePort } from "./utils"; -import { ComponentExpansionState, GRAPH_OPERATIONS } from "./types"; - -const hoverColor = getGlobalColor("--bb-ui-50"); -const nodeTextColor = getGlobalColor("--bb-neutral-900"); -const previewTextColor = getGlobalColor("--bb-neutral-500"); - -const PREVIEW_WIDTH = 170; - -export class GraphPortLabel extends PIXI.Container { - #isDirty = false; - - #width = 0; - #height = 0; - #textSize = 12; - #portTextColor = nodeTextColor; - #spacing = 4; - #radius = 4; - #paddingLeft = 4; - #paddingTop = 4; - #paddingBottom = 4; - #paddingRight = 8; - #expansionState: ComponentExpansionState = "expanded"; - - #previewTextSize = 12; - #previewTextColor = previewTextColor; - - #port: InspectablePort | null = null; - #label: PIXI.Text; - #valuePreview: PIXI.HTMLText; - #hoverZone = new PIXI.Graphics(); - - #showNodePreviewValues = false; - #isConfigurable = false; - - readOnly = false; - - constructor(port: InspectablePort, showNodePreviewValues: boolean) { - super(); - - this.#label = new PIXI.Text({ - text: port.title, - style: { - fontFamily: "Arial", - fontSize: this.#textSize, - fill: this.#portTextColor, - align: "left", - }, - }); - - this.#valuePreview = new PIXI.HTMLText({ - text: this.#createTruncatedValue(port), - style: { - fontFamily: "Arial", - fontSize: this.#previewTextSize, - tagStyles: { - div: { - fontStyle: "italic", - lineHeight: this.#previewTextSize * 1.5, - }, - }, - fill: this.#previewTextColor, - align: "left", - wordWrap: true, - wordWrapWidth: PREVIEW_WIDTH, - breakWords: false, - }, - }); - - this.#label.eventMode = "none"; - this.#valuePreview.eventMode = "none"; - - this.addChild(this.#hoverZone); - this.addChild(this.#label); - this.addChild(this.#valuePreview); - - this.#hoverZone.visible = false; - this.#valuePreview.visible = false; - this.showNodePreviewValues = showNodePreviewValues; - this.port = port; - this.#calculateDimensions(); - - this.onRender = () => { - if (!this.#isDirty) { - return; - } - this.#isDirty = false; - this.#calculateDimensions(); - this.#draw(); - }; - - this.addEventListener("pointerover", (evt: PIXI.FederatedPointerEvent) => { - if (!this.isConfigurable) { - return; - } - - const ptrEvent = evt.nativeEvent as PointerEvent; - const [top] = ptrEvent.composedPath(); - if (!(top instanceof HTMLElement)) { - return; - } - - if (top.tagName !== "CANVAS") { - return; - } - - this.#hoverZone.alpha = 1; - }); - - this.addEventListener("pointerout", () => { - if (!this.isConfigurable) { - return; - } - - this.#hoverZone.alpha = 0; - }); - - this.addEventListener("click", (evt: PIXI.FederatedPointerEvent) => { - if (!this.isConfigurable || this.readOnly) { - return; - } - - this.emit( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_VALUE_EDIT, - this.port, - evt.clientX, - evt.clientY - ); - }); - } - - set expansionState(expansionState: ComponentExpansionState) { - if (expansionState === this.#expansionState) { - return; - } - - this.#expansionState = expansionState; - this.isConfigurable = - !!this.#port && isConfigurablePort(this.#port, this.#expansionState); - this.#isDirty = true; - } - - get expansionState() { - return this.#expansionState; - } - - set port(port: InspectablePort | null) { - this.#port = port; - this.#isDirty = true; - - const portTitle = port?.title || ""; - if (portTitle !== this.#label.text) { - this.#label.text = portTitle; - } - - const valuePreview = this.#createTruncatedValue(port); - if (valuePreview !== this.#valuePreview.text) { - this.#valuePreview.text = valuePreview; - } - - if (!port) { - this.isConfigurable = false; - return; - } - - this.isConfigurable = isConfigurablePort(port, this.#expansionState); - } - - get port() { - return this.#port; - } - - get dimensions() { - return { width: this.#width, height: this.#height }; - } - - set isConfigurable(isConfigurable: boolean) { - if (isConfigurable === this.#isConfigurable) { - return; - } - - this.#isConfigurable = isConfigurable; - this.#isDirty = true; - - if (isConfigurable && !this.readOnly) { - this.eventMode = "static"; - this.#hoverZone.cursor = "pointer"; - } else { - this.eventMode = "none"; - this.#hoverZone.cursor = "default"; - } - } - - get isConfigurable() { - return this.#isConfigurable; - } - - get showNodePreviewValues() { - return this.#showNodePreviewValues; - } - - set showNodePreviewValues(showNodePreviewValues: boolean) { - if (showNodePreviewValues === this.#showNodePreviewValues) { - return; - } - - this.#calculateDimensions(); - this.#showNodePreviewValues = showNodePreviewValues; - this.#isDirty = true; - } - - get text() { - return this.#label.text ?? ""; - } - - get value() { - return this.#valuePreview.text ?? ""; - } - - #draw() { - this.#hoverZone.clear(); - - if (!this.isConfigurable || this.readOnly) { - return; - } - - this.#hoverZone.beginPath(); - this.#hoverZone.roundRect( - -this.#paddingLeft, - -this.#paddingLeft, - this.#width + this.#paddingLeft + this.#paddingRight, - this.#height + this.#paddingTop + this.#paddingBottom, - this.#radius - ); - this.#hoverZone.closePath(); - this.#hoverZone.fill({ color: hoverColor }); - - this.#hoverZone.alpha = 0; - this.#hoverZone.visible = true; - } - - #calculateDimensions() { - this.#label.x = 0; - this.#label.y = 0; - this.#valuePreview.x = 0; - this.#valuePreview.y = this.#label.height + this.#spacing; - - this.#width = Math.max(this.#label.width, this.#valuePreview.width); - this.#height = this.#label.height; - - if (this.#valuePreview.text !== "" && this.#showNodePreviewValues) { - this.#valuePreview.visible = true; - this.#width = PREVIEW_WIDTH; - this.#height += this.#spacing + this.#valuePreview.height; - } - } - - #createTruncatedValue(port: InspectablePort | null) { - if (!port) { - return ""; - } - - if (!this.#showNodePreviewValues) { - return ""; - } - - let { value } = port; - if (value === null || value === undefined) { - if ( - port.status === PortStatus.Missing && - isConfigurablePort(port, this.#expansionState) - ) { - return "(not configured)"; - } - return ""; - } - - let valStr = ""; - if (typeof value === "object") { - if (isLLMContent(value)) { - value = [value]; - } - - if (isLLMContentArray(value)) { - const firstValue = value[0]; - if (firstValue) { - const firstPart = firstValue.parts[0]; - if (isTextCapabilityPart(firstPart)) { - valStr = firstPart.text; - } else if (isInlineData(firstPart)) { - valStr = firstPart.inlineData.mimeType; - } else if (isStoredData(firstPart)) { - valStr = firstPart.storedData.mimeType; - } else { - valStr = "LLM Content Part"; - } - } else { - valStr = "0 items"; - } - } else if (Array.isArray(value)) { - valStr = `${value.length} item${value.length === 1 ? "" : "s"}`; - } - } else { - valStr = value.toString(); - } - - if (valStr.length > 60) { - valStr = `${valStr.substring(0, 60)}...`; - } - - return valStr; - } -} diff --git a/packages/shared-ui/src/elements/editor/graph-renderer.ts b/packages/shared-ui/src/elements/editor/graph-renderer.ts deleted file mode 100644 index 4ca6ae03166..00000000000 --- a/packages/shared-ui/src/elements/editor/graph-renderer.ts +++ /dev/null @@ -1,1802 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { LitElement, html, css, nothing } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import * as PIXI from "pixi.js"; -import { - GraphNodeSelectedEvent, - GraphNodeDeleteEvent, - GraphEdgeAttachEvent, - GraphNodeEdgeChangeEvent, - GraphEdgeDetachEvent, - InputErrorEvent, - GraphNodeDeselectedEvent, - GraphNodeDeselectedAllEvent, - GraphNodesVisualUpdateEvent, - GraphInitialDrawEvent, - GraphEntityRemoveEvent, - StartEvent, - GraphNodeEditEvent, - GraphEdgeValueSelectedEvent, - GraphNodeActivitySelectedEvent, - GraphInteractionEvent, - GraphShowTooltipEvent, - GraphHideTooltipEvent, - GraphCommentEditRequestEvent, -} from "../../events/events.js"; -import { ComponentExpansionState, GRAPH_OPERATIONS } from "./types.js"; -import { Graph } from "./graph.js"; -import { - InspectableEdge, - InspectableEdgeType, - InspectableNode, - InspectableNodePorts, - InspectablePort, - NodeHandlerMetadata, - Schema, -} from "@google-labs/breadboard"; -import { GraphNode } from "./graph-node.js"; -import { Ref, createRef, ref } from "lit/directives/ref.js"; -import { until } from "lit/directives/until.js"; -import { GraphAssets } from "./graph-assets.js"; -import { GraphEdge } from "./graph-edge.js"; -import { map } from "lit/directives/map.js"; -import { classMap } from "lit/directives/class-map.js"; -import { styleMap } from "lit/directives/style-map.js"; -import { computeNextExpansionState, getGlobalColor } from "./utils.js"; -import { - GraphMetadata, - NodeValue, -} from "@google-labs/breadboard-schema/graph.js"; -import { GraphComment } from "./graph-comment.js"; -import { EdgeData, TopGraphRunResult } from "../../types/types.js"; - -const backgroundColor = getGlobalColor("--bb-ui-50"); -const backgroundGridColor = getGlobalColor("--bb-ui-100"); -const backgroundGridAlpha = 0.25; -const selectionBoxBackgroundAlpha = 0.05; -const selectionBoxBackgroundColor = getGlobalColor("--bb-neutral-900"); -const selectionBoxBorderColor = getGlobalColor("--bb-neutral-500"); -const ADHOC_EDGE_ERROR_MESSAGE = - "Ad-hoc port names must only contain lowercase alphanumeric characters and '-'"; - -enum MODE { - MOVE = "move", - SELECT = "select", -} - -interface GraphOpts { - url: string; - subGraphId: string | null; - showNodePreviewValues: boolean; - showNodeTypeDescriptions: boolean; - collapseNodesByDefault: boolean; - ports: Map | null; - typeMetadata: Map | null; - edges: InspectableEdge[]; - nodes: InspectableNode[]; - metadata: GraphMetadata; - visible: boolean; -} - -@customElement("bb-graph-renderer") -export class GraphRenderer extends LitElement { - @property({ reflect: true }) - invertZoomScrollDirection = false; - - @property({ reflect: true }) - readOnly = false; - - @property({ reflect: true }) - highlightInvalidWires = false; - - @property() - showPortTooltips = false; - - @state() - private _portTooltip?: { - location: PIXI.ObservablePoint; - port: InspectablePort; - } = undefined; - - #app = new PIXI.Application(); - #appInitialized = false; - - #overflowEditNode: Ref = createRef(); - #overflowDeleteNode: Ref = createRef(); - #overflowMinMaxSingleNode: Ref = createRef(); - #overflowMenuRef: Ref = createRef(); - #overflowMenuGraphNode: GraphNode | null = null; - - #activeGraph: Graph | null = null; - #edgesForDisambiguation: InspectableEdge[] | null = null; - #menuLocation: PIXI.ObservablePoint | null = null; - #edgeSelectMenuRef: Ref = createRef(); - #edgeCreateMenuRef: Ref = createRef(); - #autoFocusSelf = false; - #newEdgeData: { - from: string; - to: string; - portsOut: InspectablePort[] | null; - portsIn: InspectablePort[] | null; - } | null = null; - - #mode = MODE.SELECT; - #padding = 50; - #container = new PIXI.Container({ - isRenderGroup: true, - }); - #containerTransforms = new Map(); - - #nodeSelection: PIXI.Graphics | null = null; - #background: PIXI.TilingSprite | null = null; - #lastContentRect: DOMRectReadOnly | null = null; - #resizeObserver = new ResizeObserver((entries) => { - if (this.#appInitialized && "resize" in this.#app) { - this.#app.resize(); - } - - if (entries.length < 1) { - return; - } - - const { contentRect } = entries[0]; - const delta = new PIXI.Point(0, 0); - if (this.#lastContentRect) { - delta.x = (contentRect.width - this.#lastContentRect.width) * 0.5; - delta.y = (contentRect.height - this.#lastContentRect.height) * 0.5; - } - - const ratio = 1 / this.#container.scale.x; - for (const child of this.#container.children) { - if (!(child instanceof Graph)) { - continue; - } - - // Inform the graph about the content rect so that it can attempt to fit - // the graph inside of it. - child.layoutRect = contentRect; - - // Reposition it to retain its center. - child.position.x += delta.x * ratio; - child.position.y += delta.y * ratio; - } - - if (this.#background) { - this.#background.tilePosition.x += delta.x * ratio; - this.#background.tilePosition.y += delta.y * ratio; - } - - this.#lastContentRect = contentRect; - }); - - #onKeyDownBound = this.#onKeyDown.bind(this); - #onKeyUpBound = this.#onKeyUp.bind(this); - #onWheelBound = this.#onWheel.bind(this); - - ready = this.#loadTexturesAndInitializeRenderer(); - zoomToHighlightedNode = false; - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: block; - position: relative; - overflow: hidden; - } - - :host(.moving) { - cursor: grabbing; - } - - :host([readonly="true"]) canvas { - touch-action: manipulation !important; - } - - canvas { - display: block; - } - - #edge-create-disambiguation-menu, - #edge-select-disambiguation-menu, - #overflow-menu, - #port-tooltip { - z-index: 1000; - display: none; - top: 0; - left: 0; - position: fixed; - box-shadow: - 0px 4px 8px 3px rgba(0, 0, 0, 0.05), - 0px 1px 3px rgba(0, 0, 0, 0.1); - background: #ffffff; - border: 1px solid var(--bb-neutral-300); - border-radius: var(--bb-grid-size-2); - overflow: auto; - } - - #port-tooltip.visible { - display: block; - } - - #edge-select-disambiguation-menu.visible, - #overflow-menu.visible { - display: grid; - grid-template-rows: var(--bb-grid-size-11); - } - - #edge-create-disambiguation-menu.visible { - display: grid; - padding: var(--bb-grid-size-2); - grid-template-columns: 1fr 16px 1fr; - align-items: center; - } - - #edge-create-disambiguation-menu #edge-create-from, - #edge-create-disambiguation-menu #edge-create-to { - grid-template-rows: var(--bb-grid-size-11); - } - - #edge-create-disambiguation-menu button, - #edge-select-disambiguation-menu button { - display: flex; - align-items: center; - background: none; - margin: 0; - padding: var(--bb-grid-size-3); - border: none; - border-bottom: 1px solid var(--bb-neutral-300); - text-align: left; - cursor: pointer; - } - - #edge-create-disambiguation-menu button { - width: 100%; - border-bottom: none; - border-radius: var(--bb-grid-size-2); - text-align: center; - } - - #edge-create-disambiguation-menu button:hover, - #edge-create-disambiguation-menu button:focus, - #edge-select-disambiguation-menu button:hover, - #edge-select-disambiguation-menu button:focus { - background: var(--bb-neutral-50); - } - - #edge-create-disambiguation-menu button.selected, - #edge-create-disambiguation-menu button.selected:hover, - #edge-create-disambiguation-menu button.selected:focus { - background: var(--bb-ui-50); - color: var(--bb-ui-600); - } - - #edge-create-disambiguation-menu button[disabled] { - cursor: auto; - } - - #edge-create-disambiguation-menu .edge-arrow, - #edge-select-disambiguation-menu button .edge-arrow { - display: block; - margin: 0 var(--bb-grid-size-2); - width: 16px; - height: 16px; - background: var(--bb-icon-edge-connector) center center / 16px 16px - no-repeat; - } - - #edge-create-disambiguation-menu .edge-arrow { - margin: 0; - } - - #edge-create-disambiguation-menu input[type="text"] { - padding: var(--bb-grid-size); - font: 400 var(--bb-body-medium) / var(--bb-body-line-height-medium) - var(--bb-font-family); - border: 1px solid var(--bb-neutral-300); - border-radius: var(--bb-grid-size); - } - - #edge-create-disambiguation-menu #confirm { - background: var(--bb-ui-100) var(--bb-icon-resume-blue) 8px 4px / 16px - 16px no-repeat; - color: var(--bb-ui-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4) 0 var(--bb-grid-size-7); - margin: calc(var(--bb-grid-size) * 2) 0 var(--bb-grid-size) 0; - width: auto; - } - - #overflow-menu button { - display: flex; - align-items: center; - background: none; - margin: 0; - padding: var(--bb-grid-size-3); - border: none; - border-bottom: 1px solid var(--bb-neutral-300); - text-align: left; - cursor: pointer; - } - - #overflow-menu button:hover, - #overflow-menu button:focus { - background: var(--bb-neutral-50); - } - - #overflow-menu button:last-of-type { - border: none; - } - - #overflow-menu button::before { - content: ""; - width: 20px; - height: 20px; - margin-right: var(--bb-grid-size-3); - } - - #overflow-menu #min-max.advanced::before { - background: var(--bb-icon-minimize) center center / 20px 20px no-repeat; - } - - #overflow-menu #min-max.expanded::before { - background: var(--bb-icon-maximize) center center / 20px 20px no-repeat; - } - - #overflow-menu #min-max.collapsed::before { - background: var(--bb-icon-maximize) center center / 20px 20px no-repeat; - } - - #overflow-menu #min-max.expanded::after { - content: "Show advanced ports"; - } - - #overflow-menu #min-max.collapsed::after { - content: "Show component ports"; - } - - #overflow-menu #min-max.advanced::after { - content: "Minimize component"; - } - - #overflow-menu #delete-node::before { - background: var(--bb-icon-delete) center center / 20px 20px no-repeat; - } - - #overflow-menu #edit-node::before { - background: var(--bb-icon-edit) center center / 20px 20px no-repeat; - } - `; - - constructor( - private minScale = 0.1, - private maxScale = 4, - private zoomFactor = 100 - ) { - super(); - - this.#app.stage.addChild(this.#container); - this.#app.stage.eventMode = "static"; - this.tabIndex = 0; - - let dragStart: PIXI.PointData | null = null; - let originalPosition: PIXI.ObservablePoint | null = null; - let tilePosition: PIXI.ObservablePoint | null = null; - - const onStageMove = (evt: PIXI.FederatedPointerEvent) => { - if (!dragStart || !originalPosition) { - return; - } - - this.classList.add("moving"); - - const dragPosition = this.#app.stage.toLocal(evt.global); - const dragDeltaX = dragPosition.x - dragStart.x; - const dragDeltaY = dragPosition.y - dragStart.y; - - this.#container.x = Math.round(originalPosition.x + dragDeltaX); - this.#container.y = Math.round(originalPosition.y + dragDeltaY); - - if (!this.#background || !tilePosition) { - return; - } - this.#background.tilePosition.x = tilePosition.x + dragDeltaX; - this.#background.tilePosition.y = tilePosition.y + dragDeltaY; - }; - - const onDragSelect = (evt: PIXI.FederatedPointerEvent) => { - if (!dragStart || !originalPosition) { - return; - } - - if (!this.#nodeSelection) { - this.#nodeSelection = new PIXI.Graphics(); - } - - const dragPosition = this.#app.stage.toLocal(evt.global); - const dragDeltaX = dragPosition.x - dragStart.x; - const dragDeltaY = dragPosition.y - dragStart.y; - - const x = Math.min(dragStart.x, dragPosition.x); - const y = Math.min(dragStart.y, dragPosition.y); - const w = Math.abs(dragDeltaX); - const h = Math.abs(dragDeltaY); - - this.#app.stage.addChild(this.#nodeSelection); - this.#nodeSelection.clear(); - this.#nodeSelection.beginPath(); - this.#nodeSelection.rect(x, y, w, h); - this.#nodeSelection.closePath(); - this.#nodeSelection.stroke({ width: 1, color: selectionBoxBorderColor }); - this.#nodeSelection.fill({ - color: selectionBoxBackgroundColor, - alpha: selectionBoxBackgroundAlpha, - }); - - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - graph.selectInRect(new PIXI.Rectangle(x, y, w, h)); - } - }; - - this.#app.stage.addListener( - "pointerdown", - (evt: PIXI.FederatedPointerEvent) => { - if (!evt.isPrimary) { - return; - } - - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - graph.deselectAllChildren(); - } - - dragStart = this.#app.stage.toLocal(evt.global); - originalPosition = this.#container.position.clone(); - - if (!this.#background) { - return; - } - tilePosition = this.#background.tilePosition.clone(); - } - ); - - this.#app.stage.addListener( - "pointermove", - (evt: PIXI.FederatedPointerEvent) => { - if (this.#mode === MODE.MOVE) { - onStageMove(evt); - return; - } - - if (!evt.isPrimary) { - return; - } - onDragSelect(evt); - } - ); - - const onPointerUp = () => { - dragStart = null; - originalPosition = null; - tilePosition = null; - - this.classList.remove("moving"); - - if (this.#nodeSelection) { - this.#nodeSelection.removeFromParent(); - this.#nodeSelection.destroy(); - this.#nodeSelection = null; - } - - this.#storeContainerTransformForVisibleGraph(); - }; - this.#app.stage.addListener("pointerup", onPointerUp); - this.#app.stage.addListener("pointerupoutside", onPointerUp); - - const onWheel = (evt: PIXI.FederatedWheelEvent) => { - // The user has interacted – stop the auto-zoom/pan. - this.zoomToHighlightedNode = false; - this.dispatchEvent(new GraphInteractionEvent()); - - if (evt.metaKey || evt.ctrlKey) { - let delta = - 1 - - (evt.deltaY / this.zoomFactor) * - (this.invertZoomScrollDirection ? -1 : 1); - const newScale = this.#container.scale.x * delta; - if (newScale < this.minScale || newScale > this.maxScale) { - delta = 1; - } - - const pivot = this.#app.stage.toLocal(evt.global); - const matrix = this.#scaleContainerAroundPoint(delta, pivot); - - if (!this.#background) { - return; - } - - this.#background.tileTransform.setFromMatrix(matrix); - } else { - this.#container.x -= evt.deltaX; - this.#container.y -= evt.deltaY; - - if (this.#background) { - this.#background.tilePosition.x -= evt.deltaX; - this.#background.tilePosition.y -= evt.deltaY; - } - } - - this.#storeContainerTransformForVisibleGraph(); - }; - - this.#app.stage.on("wheel", onWheel); - } - - #storeContainerTransformForVisibleGraph() { - const visibleGraph = this.#getVisibleGraph(); - if (!visibleGraph) { - return; - } - - const matrix = this.#container.worldTransform.clone(); - this.#storeContainerTransform(visibleGraph, matrix); - } - - #storeContainerTransform(graph: Graph, matrix: PIXI.Matrix) { - this.#containerTransforms.set(graph.label, matrix); - } - - #restoreContainerTransformForVisibleGraph() { - const visibleGraph = this.#getVisibleGraph(); - if (!visibleGraph) { - return; - } - - const matrix = this.#containerTransforms.get(visibleGraph.label); - if (!matrix) { - return; - } - - this.#container.setFromMatrix(matrix); - } - - #scaleContainerAroundPoint(delta: number, pivot: PIXI.PointData) { - const m = new PIXI.Matrix(); - m.identity() - .scale(this.#container.scale.x, this.#container.scale.y) - .translate(this.#container.x, this.#container.y); - - // Update with the mousewheel position & delta. - m.translate(-pivot.x, -pivot.y) - .scale(delta, delta) - .translate(pivot.x, pivot.y); - - // Ensure that it is always on a square pixel. - m.tx = Math.round(m.tx); - m.ty = Math.round(m.ty); - - // Apply back to the container. - this.#container.setFromMatrix(m); - return m; - } - - #notifyGraphOfEdgeSelection(edge: EdgeData) { - if (!this.#activeGraph) { - return; - } - - this.#activeGraph.selectEdge(edge); - this.#activeGraph = null; - } - - hideAllGraphs() { - for (const graph of this.#container.children) { - if (!(graph instanceof Graph)) { - continue; - } - - graph.visible = false; - } - } - - showGraph(url: string, subGraphId: string | null) { - const label = this.#createUrl(url, subGraphId); - for (const graph of this.#container.children) { - if (!(graph instanceof Graph)) { - continue; - } - - if (graph.label !== label) { - continue; - } - - graph.visible = true; - } - - this.#restoreContainerTransformForVisibleGraph(); - } - - set topGraphResult(topGraphResult: TopGraphRunResult | null) { - let highlightedNode = null; - let edgeValues = null; - let nodeValues = null; - - if (topGraphResult && topGraphResult.currentNode) { - highlightedNode = topGraphResult.currentNode; - } - - if (topGraphResult && topGraphResult.edgeValues) { - edgeValues = topGraphResult.edgeValues; - } - - if (topGraphResult && topGraphResult.nodeActivity) { - nodeValues = topGraphResult.nodeActivity; - } - - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - graph.highlightedNode = highlightedNode; - graph.edgeValues = edgeValues; - graph.nodeValues = nodeValues; - } - - if (!this.zoomToHighlightedNode || !highlightedNode) { - return; - } - - this.zoomToNode(highlightedNode.descriptor.id, -0.1); - } - - createGraph(opts: GraphOpts) { - const graph = new Graph(); - graph.label = this.#createUrl(opts.url, opts.subGraphId); - - this.#addGraph(graph); - this.updateGraphByUrl(opts.url, opts.subGraphId, opts); - } - - deleteGraphs() { - for (let c = this.#container.children.length; c >= 0; c--) { - const child = this.#container.children[c]; - if (!(child instanceof Graph)) { - continue; - } - - child.removeFromParent(); - child.destroy(); - } - } - - updateGraphByUrl( - url: string, - subGraphId: string | null, - opts: Partial - ) { - const graph = this.#container.children.find( - (child) => child.label === this.#createUrl(url, subGraphId) - ); - - if (!(graph instanceof Graph)) { - return false; - } - - graph.readOnly = this.readOnly; - graph.highlightInvalidWires = this.highlightInvalidWires; - - if (opts.showNodeTypeDescriptions !== undefined) { - graph.showNodeTypeDescriptions = opts.showNodeTypeDescriptions; - } - - if (opts.showNodePreviewValues !== undefined) { - graph.showNodePreviewValues = opts.showNodePreviewValues; - } - - if (opts.showNodeTypeDescriptions !== undefined) { - graph.showNodeTypeDescriptions = opts.showNodeTypeDescriptions; - } - - if (opts.collapseNodesByDefault !== undefined) { - graph.collapseNodesByDefault = opts.collapseNodesByDefault; - } - - if (opts.ports !== undefined) { - graph.ports = opts.ports; - } - - if (opts.edges !== undefined) { - graph.edges = opts.edges; - } - - if (opts.nodes !== undefined) { - graph.nodes = opts.nodes; - } - - if (opts.typeMetadata !== undefined) { - graph.typeMetadata = opts.typeMetadata; - } - - if (opts.metadata !== undefined) { - graph.comments = opts.metadata.comments || null; - } - - if (opts.visible !== undefined) { - graph.visible = opts.visible; - } - - return true; - } - - #createUrl(url: string, subGraphId: string | null) { - return url + (subGraphId ? `#${subGraphId}` : ""); - } - - getGraphs(): Graph[] { - return this.#container.children.filter( - (child) => child instanceof Graph - ) as Graph[]; - } - - #getVisibleGraph(): Graph | null { - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - return graph; - } - - return null; - } - - #emitSelectionState() { - this.dispatchEvent(new GraphNodeDeselectedAllEvent()); - - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - const selectedChildren = graph.getSelectedChildren(); - for (const child of selectedChildren) { - if (!(child instanceof GraphNode || child instanceof GraphComment)) { - continue; - } - - this.dispatchEvent(new GraphNodeSelectedEvent(child.label)); - } - } - } - - #addGraph(graph: Graph) { - graph.on(GRAPH_OPERATIONS.GRAPH_NODE_EXPAND_COLLAPSE, () => { - this.#emitGraphNodeVisualInformation(graph); - }); - - graph.on( - GRAPH_OPERATIONS.GRAPH_NODES_MOVED, - ( - nodes: Array<{ - id: string; - type: "node" | "comment"; - x: number; - y: number; - expansionState: ComponentExpansionState; - }> - ) => { - this.dispatchEvent(new GraphNodesVisualUpdateEvent(nodes)); - } - ); - - graph.on(GRAPH_OPERATIONS.GRAPH_NODE_SELECTED, (id: string) => { - this.dispatchEvent(new GraphNodeSelectedEvent(id)); - }); - - graph.on(GRAPH_OPERATIONS.GRAPH_NODE_DESELECTED, (id: string) => { - this.dispatchEvent(new GraphNodeDeselectedEvent(id)); - }); - - graph.on(GRAPH_OPERATIONS.GRAPH_NODE_DESELECTED_ALL, () => { - this.dispatchEvent(new GraphNodeDeselectedAllEvent()); - }); - - graph.on(GRAPH_OPERATIONS.GRAPH_EDGE_ATTACH, (edge: EdgeData) => { - this.dispatchEvent(new GraphEdgeAttachEvent(edge)); - }); - - graph.on(GRAPH_OPERATIONS.GRAPH_EDGE_DETACH, (edge: EdgeData) => { - this.dispatchEvent(new GraphEdgeDetachEvent(edge)); - }); - - graph.on( - GRAPH_OPERATIONS.GRAPH_EDGE_CHANGE, - (from: EdgeData, to: EdgeData) => { - this.dispatchEvent(new GraphNodeEdgeChangeEvent(from, to)); - } - ); - - graph.on(GRAPH_OPERATIONS.GRAPH_AUTOSELECTED_NODES, () => { - this.#emitSelectionState(); - }); - - graph.on(GRAPH_OPERATIONS.GRAPH_INITIAL_DRAW, () => { - this.dispatchEvent(new GraphInitialDrawEvent()); - }); - - graph.on(GRAPH_OPERATIONS.GRAPH_DRAW, () => { - graph.layout(); - }); - - graph.on( - GRAPH_OPERATIONS.GRAPH_NODE_MENU_REQUESTED, - (graphNode: GraphNode, location: PIXI.ObservablePoint) => { - if (!this.#overflowMenuRef.value) { - return; - } - - const overflowMenu = this.#overflowMenuRef.value; - overflowMenu.classList.add("visible"); - overflowMenu.style.translate = `${location.x}px ${location.y}px`; - - if (this.#overflowMinMaxSingleNode.value) { - this.#overflowMinMaxSingleNode.value.classList.toggle( - "expanded", - graphNode.expansionState === "expanded" - ); - this.#overflowMinMaxSingleNode.value.classList.toggle( - "collapsed", - graphNode.expansionState === "collapsed" - ); - this.#overflowMinMaxSingleNode.value.classList.toggle( - "advanced", - graphNode.expansionState === "advanced" - ); - } - - this.#overflowMenuGraphNode = graphNode; - - window.addEventListener( - "pointerdown", - (evt: PointerEvent) => { - if (!this.#overflowMenuGraphNode) { - return; - } - - const [topItem] = evt.composedPath(); - switch (topItem) { - case this.#overflowMinMaxSingleNode.value: { - this.#overflowMenuGraphNode.expansionState = - computeNextExpansionState( - this.#overflowMenuGraphNode.expansionState - ); - break; - } - - case this.#overflowEditNode.value: { - if (!this.#overflowMenuGraphNode.label) { - console.warn("Tried to delete unnamed node"); - break; - } - - this.dispatchEvent( - new GraphNodeEditEvent( - this.#overflowMenuGraphNode.label, - null, - evt.clientX, - evt.clientY, - false - ) - ); - break; - } - - case this.#overflowDeleteNode.value: { - if (!this.#overflowMenuGraphNode.label) { - console.warn("Tried to delete unnamed node"); - break; - } - - this.dispatchEvent( - new GraphNodeDeleteEvent(this.#overflowMenuGraphNode.label) - ); - break; - } - } - - overflowMenu.classList.remove("visible"); - this.#overflowMenuGraphNode = null; - }, - { once: true } - ); - } - ); - - graph.on( - GRAPH_OPERATIONS.GRAPH_EDGE_SELECT_DISAMBIGUATION_REQUESTED, - (possibleEdges: InspectableEdge[], location: PIXI.ObservablePoint) => { - this.#activeGraph = graph; - this.#edgesForDisambiguation = possibleEdges; - this.#menuLocation = location; - - this.requestUpdate(); - } - ); - - graph.on( - GRAPH_OPERATIONS.GRAPH_EDGE_ADD_DISAMBIGUATION_REQUESTED, - ( - from: string, - to: string, - portsOut: InspectablePort[], - portsIn: InspectablePort[], - location: PIXI.ObservablePoint - ) => { - this.#activeGraph = graph; - this.#newEdgeData = { - from, - to, - portsOut, - portsIn, - }; - this.#menuLocation = location; - - this.requestUpdate(); - } - ); - - graph.on( - GRAPH_OPERATIONS.GRAPH_EDGE_ADD_AD_HOC_DISAMBIGUATION_REQUESTED, - ( - from: string, - to: string, - portsOut: InspectablePort[] | null, - portsIn: InspectablePort[] | null, - location: PIXI.ObservablePoint - ) => { - this.#activeGraph = graph; - this.#newEdgeData = { - from, - to, - portsOut, - portsIn, - }; - this.#menuLocation = location; - - this.requestUpdate(); - } - ); - - graph.on(GRAPH_OPERATIONS.GRAPH_BOARD_LINK_CLICKED, (board: string) => { - this.dispatchEvent(new StartEvent(board)); - }); - - graph.on( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_MOUSEENTER, - (port: InspectablePort, location: PIXI.ObservablePoint) => { - this._portTooltip = { port, location }; - } - ); - - graph.on(GRAPH_OPERATIONS.GRAPH_NODE_PORT_MOUSELEAVE, () => { - this._portTooltip = undefined; - }); - - graph.on( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_VALUE_EDIT, - (id: string, port: InspectablePort | null, x: number, y: number) => { - this.dispatchEvent(new GraphNodeEditEvent(id, port, x, y)); - } - ); - - graph.on( - GRAPH_OPERATIONS.GRAPH_EDGE_VALUE_SELECTED, - (value: NodeValue[], schema: Schema | null, x: number, y: number) => { - this.dispatchEvent( - new GraphEdgeValueSelectedEvent(value, schema, x, y) - ); - } - ); - - graph.on( - GRAPH_OPERATIONS.GRAPH_NODE_ACTIVITY_SELECTED, - (nodeName: string, id: string) => { - this.dispatchEvent(new GraphNodeActivitySelectedEvent(nodeName, id)); - } - ); - - graph.on( - GRAPH_OPERATIONS.GRAPH_SHOW_TOOLTIP, - (message: string, x: number, y: number) => { - this.dispatchEvent(new GraphShowTooltipEvent(message, x, y)); - } - ); - - graph.on(GRAPH_OPERATIONS.GRAPH_HIDE_TOOLTIP, () => { - this.dispatchEvent(new GraphHideTooltipEvent()); - }); - - graph.on( - GRAPH_OPERATIONS.GRAPH_COMMENT_EDIT_REQUESTED, - (label: string, x: number, y: number) => { - this.dispatchEvent(new GraphCommentEditRequestEvent(label, x, y)); - } - ); - - this.#container.addChild(graph); - } - - removeGraph(graph: Graph) { - graph.removeFromParent(); - graph.destroy(); - } - - removeAllGraphs() { - for (const graph of this.#container.children) { - if (!(graph instanceof Graph)) { - continue; - } - - this.removeGraph(graph); - } - } - - getSelectedChildren() { - const selected: Array = []; - - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - selected.push(...graph.getSelectedChildren()); - } - - return selected; - } - - deselectAllChildren() { - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - graph.deselectAllChildren(); - } - } - - toGlobal(point: PIXI.PointData) { - for (const graph of this.#container.children) { - if (!(graph instanceof Graph)) { - continue; - } - - return graph.toGlobal(point); - } - - return point; - } - - setNodeLayoutPosition( - node: string, - type: "comment" | "node", - position: PIXI.PointData, - expansionState: ComponentExpansionState, - justAdded: boolean - ) { - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - return graph.setNodeLayoutPosition( - node, - type, - position, - expansionState, - justAdded - ); - } - - return null; - } - - getNodeLayoutPosition(node: string) { - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - return graph.getNodeLayoutPosition(node); - } - - return null; - } - - addToAutoSelect(node: string) { - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - return graph.addToAutoSelect(node); - } - } - - zoomToNode(id: string, offset = 0) { - this.zoomToFit(false); - - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - const graphNode = graph.getChildByLabel(id); - if (!graphNode) { - continue; - } - - const graphBounds = graph.getBounds(); - const graphNodeBounds = graphNode.getBounds(); - const rendererBounds = this.getBoundingClientRect(); - - const xShift = - (0.5 + - offset - - (graphNodeBounds.x - graphBounds.x + graphNodeBounds.width * 0.5) / - graphBounds.width) * - graphBounds.width; - this.#container.x += xShift; - - const yShift = - (0.5 - - (graphNodeBounds.y - graphBounds.y + graphNodeBounds.height * 0.5) / - graphBounds.height) * - graphBounds.height; - this.#container.y += yShift; - - let delta = Math.min( - (rendererBounds.width - 2 * this.#padding) / graphNodeBounds.width, - (rendererBounds.height - 2 * this.#padding) / graphNodeBounds.height - ); - - const zoomNodeMaxScale = this.maxScale * 0.5; - if (delta < this.minScale) { - delta = this.minScale; - } else if (delta > zoomNodeMaxScale) { - delta = zoomNodeMaxScale; - } - - const pivot = { - x: rendererBounds.width / 2, - y: rendererBounds.height / 2, - }; - - const matrix = this.#scaleContainerAroundPoint(delta, pivot); - this.#storeContainerTransform(graph, matrix); - return; - } - } - - zoomToFit(emitGraphNodeVisualInformation = true) { - this.#container.scale.set(1, 1); - - // Find the first graph in the container and size to it. - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - const graphPosition = graph.getGlobalPosition(); - const graphBounds = graph.getBounds(); - const rendererBounds = this.getBoundingClientRect(); - - // Dagre isn't guaranteed to start the layout at 0, 0, so we adjust things - // back here so that the scaling calculations work out. - graphBounds.x -= graphPosition.x; - graphBounds.y -= graphPosition.y; - graph.position.set(-graphBounds.x, -graphBounds.y); - this.#container.position.set( - (rendererBounds.width - graphBounds.width) * 0.5, - (rendererBounds.height - graphBounds.height) * 0.5 - ); - const delta = Math.min( - (rendererBounds.width - 2 * this.#padding) / graphBounds.width, - (rendererBounds.height - 2 * this.#padding) / graphBounds.height, - 1 - ); - - if (delta < this.minScale) { - this.minScale = delta; - } - - const pivot = { - x: rendererBounds.width / 2, - y: rendererBounds.height / 2, - }; - - const matrix = this.#scaleContainerAroundPoint(delta, pivot); - if (emitGraphNodeVisualInformation) { - this.#emitGraphNodeVisualInformation(graph); - } - - this.#storeContainerTransform(graph, matrix); - return; - } - } - - #emitGraphNodeVisualInformation(graph: Graph) { - const positions = graph.getNodeLayoutPositions(); - const nodes = [...positions.entries()].map(([id, layout]) => { - return { - id, - type: layout.type, - x: layout.x, - y: layout.y, - expansionState: layout.expansionState, - }; - }); - - this.dispatchEvent(new GraphNodesVisualUpdateEvent(nodes)); - } - - resetGraphLayout() { - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - graph.clearNodeLayoutPositions(); - graph.storeCommentLayoutPositions(); - graph.layout(); - - this.#emitGraphNodeVisualInformation(graph); - } - } - - selectAll() { - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - graph.selectAll(); - } - } - - #onKeyDown(evt: KeyboardEvent) { - if (evt.code === "KeyA" && evt.metaKey) { - if (evt.composedPath()[0] !== this) { - return; - } - - this.selectAll(); - return; - } - - if (evt.code === "Space") { - this.#mode = MODE.MOVE; - return; - } - - if (evt.code !== "Backspace") { - return; - } - - const [target] = evt.composedPath(); - if (target !== this) { - return; - } - - for (const graph of this.#container.children) { - if (!(graph instanceof Graph) || !graph.visible) { - continue; - } - - const selectedChildren = graph.getSelectedChildren(); - if (!selectedChildren.length) { - continue; - } - - const nodes: string[] = []; - const edges: EdgeData[] = []; - const comments: string[] = []; - for (const child of selectedChildren) { - if (child instanceof GraphNode) { - nodes.push(child.label); - } else if (child instanceof GraphComment) { - comments.push(child.label); - } else if (child instanceof GraphEdge && child.edge) { - edges.push(child.edge); - } - } - - this.dispatchEvent(new GraphEntityRemoveEvent(nodes, edges, comments)); - } - } - - #onKeyUp(evt: KeyboardEvent) { - if (evt.code !== "Space") { - return; - } - - this.#mode = MODE.SELECT; - } - - #onWheel(evt: WheelEvent) { - evt.preventDefault(); - } - - connectedCallback(): void { - super.connectedCallback(); - - this.#resizeObserver.observe(this); - window.addEventListener("keyup", this.#onKeyUpBound); - window.addEventListener("keydown", this.#onKeyDownBound); - this.addEventListener("wheel", this.#onWheelBound, { passive: false }); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - - if ("stop" in this.#app) { - this.#app.stop(); - } - - this.#resizeObserver.disconnect(); - window.removeEventListener("keyup", this.#onKeyUpBound); - window.removeEventListener("keydown", this.#onKeyDownBound); - this.removeEventListener("wheel", this.#onWheelBound); - } - - async #loadTexturesAndInitializeRenderer() { - if (this.#appInitialized) { - return this.#app.canvas; - } - - await Promise.all([ - GraphAssets.instance().loaded, - this.#app.init({ - webgl: { - background: backgroundColor, - antialias: true, - }, - preference: "webgl", - resizeTo: this, - autoDensity: true, - resolution: Math.max(2, window.devicePixelRatio), - eventMode: "static", - eventFeatures: { - globalMove: true, - move: true, - click: true, - wheel: true, - }, - }), - ]); - - if (!this.#background) { - const canvas = document.createElement("canvas"); - canvas.width = 32; - canvas.height = 32; - const ctx = canvas.getContext("2d"); - if (!ctx) { - console.warn("Unable to create background texture"); - return; - } - - // Solid blue background. - ctx.fillStyle = `#${backgroundColor.toString(16)}`; - ctx.fillRect(0, 0, 32, 32); - - // Grid. - ctx.save(); - ctx.strokeStyle = `#${backgroundGridColor.toString(16)}`; - ctx.beginPath(); - ctx.rect(0.5, 0.5, 32, 32); - ctx.globalAlpha = backgroundGridAlpha; - ctx.stroke(); - ctx.closePath(); - ctx.restore(); - - const texture = PIXI.Texture.from(canvas); - - this.#background = new PIXI.TilingSprite(texture); - this.#background.width = this.#app.canvas.width; - this.#background.height = this.#app.canvas.height; - - this.#app.stage.addChildAt(this.#background, 0); - } else { - this.#app.stage.addChildAt(this.#background, 0); - } - - this.#app.start(); - this.#app.resize(); - this.#app.renderer.addListener("resize", () => { - if (!this.#background) { - return; - } - - this.#background.width = this.#app.renderer.width; - this.#background.height = this.#app.renderer.height; - }); - - this.#appInitialized = true; - return this.#app.canvas; - } - - protected updated(): void { - if ( - (this.#edgesForDisambiguation && this.#edgeSelectMenuRef.value) || - (this.#newEdgeData && this.#edgeCreateMenuRef.value) - ) { - window.addEventListener( - "pointerdown", - () => { - this.#edgesForDisambiguation = null; - this.#newEdgeData = null; - this.#autoFocusSelf = true; - this.requestUpdate(); - }, - { once: true } - ); - - const input = this.#edgeCreateMenuRef.value?.querySelector("input"); - if (input) { - input.focus(); - } - } - - if (this.#autoFocusSelf) { - this.#autoFocusSelf = false; - requestAnimationFrame(() => { - this.focus(); - }); - } - } - - #createEdgeIfPossible() { - if (!this.#edgeCreateMenuRef.value) { - return false; - } - - if (!this.#newEdgeData) { - return false; - } - - if (!this.#activeGraph) { - return false; - } - - const menu = this.#edgeCreateMenuRef.value; - const lhsButton = menu.querySelector( - "#edge-create-from .selected" - ); - const lhsInput = menu.querySelector( - "#edge-create-from input" - ); - const rhsButton = menu.querySelector( - "#edge-create-to .selected" - ); - const rhsInput = menu.querySelector( - "#edge-create-to input" - ); - - if (!(lhsButton || lhsInput) || !(rhsButton || rhsInput)) { - return false; - } - - let inPortName: string | null = null; - let outPortName: string | null = null; - if (lhsButton) { - outPortName = lhsButton.dataset.portName || null; - } else if (lhsInput) { - if (lhsInput.value !== "" && !lhsInput.checkValidity()) { - const evt = new InputErrorEvent(ADHOC_EDGE_ERROR_MESSAGE); - this.dispatchEvent(evt); - return false; - } - - outPortName = lhsInput.value || null; - } - if (rhsButton) { - inPortName = rhsButton.dataset.portName || null; - } else if (rhsInput) { - if (rhsInput.value !== "" && !rhsInput.checkValidity()) { - const evt = new InputErrorEvent(ADHOC_EDGE_ERROR_MESSAGE); - this.dispatchEvent(evt); - return false; - } - - inPortName = rhsInput.value || null; - } - - if (!(outPortName && inPortName)) { - return false; - } - - const newEdgeDisambiguationInfo = this.#newEdgeData; - const existingEdge = this.#activeGraph.edges?.find((edge) => { - return ( - edge.from.descriptor.id === newEdgeDisambiguationInfo.from && - edge.to.descriptor.id === newEdgeDisambiguationInfo.to && - edge.out === outPortName && - edge.in === inPortName - ); - }); - - if (existingEdge) { - return true; - } - - // TODO: Support non-ordinary wires here? - const edge = { - from: { descriptor: { id: this.#newEdgeData.from } }, - to: { descriptor: { id: this.#newEdgeData.to } }, - out: outPortName, - in: inPortName, - type: InspectableEdgeType.Ordinary, - }; - - this.dispatchEvent(new GraphEdgeAttachEvent(edge)); - - return true; - } - - render() { - const overflowMenu = html`
    - ${!this.readOnly - ? html` ` - : nothing} - - ${!this.readOnly - ? html` ` - : nothing} -
    `; - - const edgeSelectDisambiguationMenuLocation: PIXI.Point = - this.#menuLocation || new PIXI.Point(0, 0); - const edgeSelectDisambiguationMenu = html`
    - ${this.#edgesForDisambiguation - ? map(this.#edgesForDisambiguation, (edge) => { - const labelOut = edge.from.ports().then((portInfo) => { - const port = portInfo.outputs.ports.find( - (port) => port.name === edge.out - ); - if (!port) { - return html`${edge.out}`; - } - - return html`${port.title ?? port.name}`; - }); - - const labelIn = edge.to.ports().then((portInfo) => { - const port = portInfo.inputs.ports.find( - (port) => port.name === edge.in - ); - if (!port) { - return html`${edge.out}`; - } - - return html`${port.title ?? port.name}`; - }); - - return html``; - }) - : html`No edges require disambiguation`} -
    `; - - const menuLocation: PIXI.Point = this.#menuLocation || new PIXI.Point(0, 0); - const menuRequiresConfirmation = - this.#newEdgeData && - (this.#newEdgeData.portsIn === null || - this.#newEdgeData.portsOut === null); - - let suppliedPortInName: string | null = null; - let suppliedPortOutName: string | null = null; - - if (this.#newEdgeData) { - const canSupplyInPortName = - this.#newEdgeData.portsOut !== null && - this.#newEdgeData.portsOut.length === 1; - const canSupplyOutPortName = - this.#newEdgeData.portsIn !== null && - this.#newEdgeData.portsIn.length === 1; - - if (canSupplyInPortName && this.#newEdgeData.portsOut !== null) { - suppliedPortInName = this.#newEdgeData.portsOut[0].name; - } - - if (canSupplyOutPortName && this.#newEdgeData.portsIn !== null) { - suppliedPortOutName = this.#newEdgeData.portsIn[0].name; - } - } - - const edgeMenu = this.#newEdgeData - ? html`
    -
    - ${this.#newEdgeData.portsOut && this.#newEdgeData.portsOut.length - ? this.#newEdgeData.portsOut.map((port, _idx, ports) => { - return html``; - }) - : this.#newEdgeData.portsOut === null - ? html` { - evt.stopImmediatePropagation(); - }} - @keydown=${(evt: KeyboardEvent) => { - evt.stopImmediatePropagation(); - if (evt.key !== "Enter") { - return; - } - - if (!this.#createEdgeIfPossible()) { - return; - } - - window.dispatchEvent(new Event("pointerdown")); - }} - .value=${suppliedPortOutName} - type="text" - placeholder="Enter port name" - required - pattern="^[a-z0-9\\-]+$" - />` - : html`No outgoing ports`} -
    - -
    - ${this.#newEdgeData.portsIn && this.#newEdgeData.portsIn.length - ? this.#newEdgeData.portsIn.map((port, _idx, ports) => { - return html``; - }) - : this.#newEdgeData.portsIn === null - ? html` { - evt.stopImmediatePropagation(); - }} - @keydown=${(evt: KeyboardEvent) => { - evt.stopImmediatePropagation(); - if (evt.key !== "Enter") { - return; - } - - if (!this.#createEdgeIfPossible()) { - return; - } - - window.dispatchEvent(new Event("pointerdown")); - }} - .value=${suppliedPortInName} - type="text" - placeholder="Enter port name" - required - pattern="^[a-z0-9\\-]+$" - />` - : html`No incoming ports`} -
    - ${menuRequiresConfirmation - ? html`
    - -
    ` - : nothing} -
    ` - : nothing; - - return [ - until(this.ready), - overflowMenu, - edgeSelectDisambiguationMenu, - edgeMenu, - this.#renderPortTooltip(), - ]; - } - - #renderPortTooltip() { - if (!this.showPortTooltips) { - return; - } - const { port, location } = this._portTooltip ?? {}; - return html``; - } -} diff --git a/packages/shared-ui/src/elements/editor/graph.ts b/packages/shared-ui/src/elements/editor/graph.ts deleted file mode 100644 index ec7cb66b384..00000000000 --- a/packages/shared-ui/src/elements/editor/graph.ts +++ /dev/null @@ -1,1737 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - CommentNode, - InspectableEdge, - InspectableEdgeType, - InspectableNode, - InspectableNodePorts, - InspectablePort, - NodeHandlerMetadata, - PortStatus, -} from "@google-labs/breadboard"; -import * as PIXI from "pixi.js"; -import * as Dagre from "@dagrejs/dagre"; -import { GraphEdge } from "./graph-edge.js"; -import { GraphNode } from "./graph-node.js"; -import { GraphNodePort } from "./graph-node-port.js"; -import { - ComponentExpansionState, - GRAPH_OPERATIONS, - GraphNodePortType, - LayoutInfo, - VisualMetadata, -} from "./types.js"; -import { GraphAssets } from "./graph-assets.js"; -import { - inspectableEdgeToString, - getGlobalColor, - expansionStateFromMetadata, -} from "./utils.js"; -import { GraphComment } from "./graph-comment.js"; -import { - ComponentWithActivity, - EdgeData, - TopGraphEdgeValues, - TopGraphNodeActivity, - cloneEdgeData, -} from "../../types/types.js"; - -const highlightedNodeColor = getGlobalColor("--bb-ui-600"); - -const nodeColors = new Map([ - [ - "specialist", - { - text: getGlobalColor("--bb-specialist-600"), - border: getGlobalColor("--bb-neutral-500"), - }, - ], - [ - "runJavascript", - { - text: getGlobalColor("--bb-js-700"), - border: getGlobalColor("--bb-neutral-500"), - }, - ], - [ - "input", - { - text: getGlobalColor("--bb-input-600"), - border: getGlobalColor("--bb-neutral-500"), - }, - ], - [ - "output", - { - text: getGlobalColor("--bb-output-600"), - border: getGlobalColor("--bb-neutral-400"), - }, - ], - [ - "human", - { - text: getGlobalColor("--bb-human-600"), - border: getGlobalColor("--bb-neutral-500"), - }, - ], - [ - "looper", - { - text: getGlobalColor("--bb-looper-600"), - border: getGlobalColor("--bb-neutral-500"), - }, - ], - [ - "joiner", - { - text: getGlobalColor("--bb-joiner-600"), - border: getGlobalColor("--bb-neutral-500"), - }, - ], -]); - -const nodeIcons = new Map([ - [ - "runJavascript", - { - name: "js", - }, - ], - [ - "input", - { - name: "input", - }, - ], - [ - "output", - { - name: "output", - }, - ], -]); - -const defaultNodeColors = { - text: getGlobalColor("--bb-neutral-600"), - border: getGlobalColor("--bb-neutral-400"), -}; - -export class Graph extends PIXI.Container { - #isDirty = true; - #edgeContainer = new PIXI.Container(); - #edgeGraphics = new Map(); - #edges: InspectableEdge[] | null = null; - #nodes: InspectableNode[] | null = null; - #typeMetadata: Map | null = null; - #comments: CommentNode[] | null = null; - #ports: Map | null = null; - #nodeById = new Map(); - #graphNodeById = new Map(); - #layout = new Map(); - #highlightedComponent: ComponentWithActivity | null = null; - #highlightedNode = new PIXI.Graphics(); - #highlightedNodeColor = highlightedNodeColor; - #highlightPadding = 8; - #autoSelect = new Set(); - #latestPendingValidateRequest = new WeakMap(); - #edgeValues: TopGraphEdgeValues | null = null; - #nodeValues: TopGraphNodeActivity | null = null; - - #isInitialDraw = true; - #collapseNodesByDefault = false; - #showNodePreviewValues = false; - #showNodeTypeDescriptions = false; - layoutRect: DOMRectReadOnly | null = null; - - readOnly = false; - highlightInvalidWires = false; - - constructor() { - super({ - isRenderGroup: true, - }); - - this.isRenderGroup = true; - this.eventMode = "static"; - this.sortableChildren = true; - - let lastHoverPort: GraphNodePort | null = null; - let lastHoverNode: GraphNode | null = null; - let nodePortBeingEdited: GraphNodePort | null = null; - let nodePortType: GraphNodePortType | null = null; - let nodeBeingEdited: GraphNode | null = null; - let edgeBeingEdited: GraphEdge | null = null; - let originalEdgeDescriptor: EdgeData | null = null; - let visibleOnNextMove = false; - let creatingAdHocEdge = false; - - this.onRender = () => { - if (!this.#isDirty) { - return; - } - - this.#isDirty = false; - this.#drawComments(); - this.#drawEdges(); - this.#drawNodes(); - this.#drawNodeHighlight(); - - if (this.#autoSelect.size > 0) { - this.#performAutoSelect(); - } - }; - - this.once("removed", () => { - // Clean all edges. - for (const edge of this.#edgeContainer.children) { - edge.removeFromParent(); - edge.destroy(); - } - - // Clean all nodes. - for (const node of this.#graphNodeById.values()) { - node.removeFromParent(); - node.destroy(); - } - - this.#edgeGraphics.clear(); - this.#graphNodeById.clear(); - this.#layout.clear(); - }); - - this.addListener("pointerdown", (evt: PIXI.FederatedPointerEvent) => { - if (!evt.isPrimary) { - return; - } - - evt.stopPropagation(); - - // Because the edge is made up the wire graphic and the value widget we - // need to redirect clicks on the wire graphic itself to the containing - // GraphEdge for the purposes of selection. - if (evt.target.label === "GraphEdge" && evt.target.parent) { - evt.target = evt.target.parent; - } - - if ( - evt.target instanceof GraphComment || - evt.target instanceof GraphNode || - evt.target instanceof GraphEdge - ) { - if (!evt.metaKey && !evt.shiftKey && !evt.target.selected) { - this.deselectAllChildren(); - } - - if (evt.target instanceof GraphEdge) { - if (evt.target.toNode.collapsed || evt.target.fromNode.collapsed) { - const possibleEdges = this.#edgesBetween( - evt.target.fromNode, - evt.target.toNode - ); - - if (possibleEdges.length === 1) { - evt.target.selected = true; - return; - } - - const requestDisambiguation = () => { - this.emit( - GRAPH_OPERATIONS.GRAPH_EDGE_SELECT_DISAMBIGUATION_REQUESTED, - possibleEdges, - evt.client - ); - }; - - this.once("pointerup", requestDisambiguation); - return; - } - } - - if (evt.metaKey) { - evt.target.selected = !evt.target.selected; - } else { - evt.target.selected = true; - } - - if ( - evt.target instanceof GraphNode || - evt.target instanceof GraphComment - ) { - this.emit( - evt.target.selected - ? GRAPH_OPERATIONS.GRAPH_NODE_SELECTED - : GRAPH_OPERATIONS.GRAPH_NODE_DESELECTED, - evt.target.label - ); - } - - this.#sortChildrenBySelectedStatus(); - return; - } - - if (this.readOnly) { - return; - } - - if (evt.target instanceof GraphNodePort) { - nodePortBeingEdited = evt.target; - nodeBeingEdited = evt.target.parent as GraphNode; - nodePortBeingEdited.overrideStatus = PortStatus.Connected; - - switch (nodePortBeingEdited.type) { - case GraphNodePortType.OUT: { - originalEdgeDescriptor = { - from: { descriptor: { id: nodeBeingEdited.label } }, - to: { descriptor: { id: nodeBeingEdited.label } }, - out: nodePortBeingEdited.label, - in: "*", - type: InspectableEdgeType.Ordinary, - }; - - edgeBeingEdited = this.#createTemporaryEdge(originalEdgeDescriptor); - if (!edgeBeingEdited) { - return; - } - nodePortType = GraphNodePortType.IN; - break; - } - - case GraphNodePortType.IN: { - // Both nodes need to be open before a change can be made. Otherwise - // we don't know exactly which edge is being edited. - if ( - edgeBeingEdited && - (edgeBeingEdited.toNode.collapsed || - edgeBeingEdited.fromNode.collapsed) - ) { - edgeBeingEdited = null; - return; - } - - nodePortType = GraphNodePortType.IN; - if (!edgeBeingEdited) { - originalEdgeDescriptor = { - from: { descriptor: { id: nodeBeingEdited.label } }, - to: { descriptor: { id: nodeBeingEdited.label } }, - out: "*", - in: nodePortBeingEdited.label, - type: InspectableEdgeType.Ordinary, - }; - - edgeBeingEdited = this.#createTemporaryEdge( - originalEdgeDescriptor - ); - if (!edgeBeingEdited) { - nodePortType = null; - nodePortBeingEdited = null; - nodeBeingEdited = null; - break; - } - nodePortType = GraphNodePortType.OUT; - } - - originalEdgeDescriptor = cloneEdgeData(edgeBeingEdited.edge); - break; - } - } - - if (!edgeBeingEdited || !edgeBeingEdited.temporary) { - return; - } - - // Hide the edge initially. - visibleOnNextMove = false; - edgeBeingEdited.visible = false; - } - }); - - this.addListener("globalpointermove", (evt: PIXI.FederatedPointerEvent) => { - if ( - !edgeBeingEdited || - !nodeBeingEdited || - !originalEdgeDescriptor || - !evt.isPrimary - ) { - return; - } - - if (!edgeBeingEdited.edge) { - console.warn("Unable to update temporary edge value"); - return; - } - - if (visibleOnNextMove) { - edgeBeingEdited.forceRedraw(); - edgeBeingEdited.visible = true; - } - - const path = evt.composedPath(); - const topTarget = path[path.length - 1]; - - if ( - topTarget instanceof GraphNodePort && - topTarget.type === nodePortType && - visibleOnNextMove - ) { - // Snap to nearest port. - topTarget.overrideStatus = PortStatus.Connected; - lastHoverPort = topTarget; - - const nodeBeingTargeted = topTarget.parent as GraphNode; - - if (nodePortType === GraphNodePortType.IN) { - edgeBeingEdited.toNode = nodeBeingTargeted; - edgeBeingEdited.edge.in = topTarget.label || ""; - edgeBeingEdited.edge.to = { - descriptor: { id: nodeBeingTargeted.label }, - }; - } else { - edgeBeingEdited.fromNode = nodeBeingTargeted; - edgeBeingEdited.edge.out = topTarget.label || ""; - edgeBeingEdited.edge.from = { - descriptor: { id: nodeBeingTargeted.label }, - }; - } - - edgeBeingEdited.overrideColor = 0xffa500; - edgeBeingEdited.overrideInLocation = null; - edgeBeingEdited.overrideOutLocation = null; - - if (lastHoverNode) { - lastHoverNode.highlightForAdHoc = false; - creatingAdHocEdge = false; - } - } else { - // Track mouse. - if (nodePortType === GraphNodePortType.IN) { - edgeBeingEdited.toNode = nodeBeingEdited; - edgeBeingEdited.edge.in = originalEdgeDescriptor.in; - edgeBeingEdited.edge.to = originalEdgeDescriptor.to; - - if (!edgeBeingEdited.overrideInLocation) { - edgeBeingEdited.overrideInLocation = - nodeBeingEdited.position.clone(); - } - - nodeBeingEdited.toLocal( - evt.global, - undefined, - edgeBeingEdited.overrideInLocation - ); - } else { - edgeBeingEdited.fromNode = nodeBeingEdited; - edgeBeingEdited.edge.out = originalEdgeDescriptor.out; - edgeBeingEdited.edge.from = originalEdgeDescriptor.from; - - if (!edgeBeingEdited.overrideOutLocation) { - edgeBeingEdited.overrideOutLocation = - nodeBeingEdited.position.clone(); - } - - nodeBeingEdited.toLocal( - evt.global, - undefined, - edgeBeingEdited.overrideOutLocation - ); - } - - edgeBeingEdited.overrideColor = 0xffcc00; - - if (lastHoverPort) { - lastHoverPort.overrideStatus = null; - lastHoverPort = null; - } - - if (!visibleOnNextMove) { - visibleOnNextMove = true; - } - - // If the user drags over a node itself and it supports ad hoc edge - // creation then highlight the target node. - if ( - nodePortBeingEdited && - nodePortBeingEdited.label !== "*" && - nodePortBeingEdited.label !== "" && - topTarget instanceof GraphNode && - topTarget !== nodeBeingEdited - ) { - const targetAllowsAdHocPorts = - (nodePortBeingEdited.type === GraphNodePortType.IN && - !topTarget.fixedOutputs) || - (nodePortBeingEdited.type === GraphNodePortType.OUT && - !topTarget.fixedInputs); - - if (targetAllowsAdHocPorts) { - topTarget.highlightForAdHoc = true; - creatingAdHocEdge = true; - lastHoverNode = topTarget; - } - } else if (lastHoverNode) { - lastHoverNode.highlightForAdHoc = false; - creatingAdHocEdge = false; - } - } - - edgeBeingEdited.forceRedraw(); - }); - - const onPointerUp = (evt: PIXI.FederatedPointerEvent) => { - if (!edgeBeingEdited || !edgeBeingEdited.edge) { - return; - } - - const path = evt.composedPath(); - const topTarget = path[path.length - 1] as PIXI.Graphics; - - // Take a copy of the info we need. - const targetNodePort = nodePortBeingEdited; - const targetEdge = edgeBeingEdited; - const targetEdgeDescriptor = cloneEdgeData(targetEdge.edge)!; - const targetHoverNodeForAdHoc = lastHoverNode; - - // Clean all the variables. - nodePortBeingEdited = null; - nodeBeingEdited = null; - edgeBeingEdited = null; - visibleOnNextMove = false; - lastHoverNode = null; - - // If the pointer target is the same at pointerdown and pointerup, the - // user has clicked on a node port, and we should avoid creating a wire. - if (topTarget === nodePortBeingEdited) { - return; - } - - let fromNode = targetEdge.fromNode; - let toNode = targetEdge.toNode; - let outPortDisambiguation = targetEdge.fromNode.outPorts; - let inPortDisambiguation = targetEdge.toNode.inPorts; - let targetInPortName = "_UNSPECIFIED_IN_PORT"; - let targetOutPortName = "_UNSPECIFIED_OUT_PORT"; - - if (targetNodePort) { - if (targetNodePort.type === GraphNodePortType.IN) { - targetInPortName = targetNodePort.label; - targetOutPortName = topTarget.label; - } else { - targetInPortName = topTarget.label; - targetOutPortName = targetNodePort.label; - } - } - - if (targetHoverNodeForAdHoc) { - targetHoverNodeForAdHoc.highlightForAdHoc = false; - if (targetNodePort) { - if (targetNodePort.type === GraphNodePortType.IN) { - fromNode = targetHoverNodeForAdHoc; - outPortDisambiguation = targetHoverNodeForAdHoc.outPorts; - } else { - toNode = targetHoverNodeForAdHoc; - inPortDisambiguation = targetHoverNodeForAdHoc.inPorts; - } - } - } - - let action: GRAPH_OPERATIONS | null = null; - if (topTarget instanceof GraphNodePort) { - if (targetEdge.temporary) { - action = GRAPH_OPERATIONS.GRAPH_EDGE_ATTACH; - } else if (originalEdgeDescriptor) { - action = GRAPH_OPERATIONS.GRAPH_EDGE_CHANGE; - } - } - - // Update the edge if either of the nodes is collapsed. - const fromNodePortsOut = outPortDisambiguation || []; - const possiblePortsOut: InspectablePort[] = fromNode.collapsed - ? fromNodePortsOut.filter((port) => !port.star && port.name !== "") - : fromNodePortsOut.filter( - (port) => - !port.star && port.name !== "" && port.name === targetOutPortName - ); - - const toNodePortsIn = inPortDisambiguation || []; - const possiblePortsIn: InspectablePort[] = toNode.collapsed - ? toNodePortsIn.filter((port) => { - if (port.star) return false; - if (port.name === "") return false; - if (port.schema.behavior?.includes("config")) return false; - const items = port.schema.items; - if ( - items && - !Array.isArray(items) && - items.behavior?.includes("config") - ) { - return false; - } - - return true; - }) - : toNodePortsIn.filter( - (port) => - !port.star && port.name !== "" && port.name === targetInPortName - ); - - if (action !== null && (fromNode.collapsed || toNode.collapsed)) { - if (targetEdge.temporary) { - this.#removeStaleEdges(); - } - - if (targetNodePort) { - targetNodePort.overrideStatus = null; - } - - if (topTarget instanceof GraphNodePort) { - topTarget.overrideStatus = null; - } - - if ( - !(topTarget instanceof GraphNodePort) || - topTarget === targetNodePort - ) { - return; - } - - if (possiblePortsOut.length === 1 && possiblePortsIn.length === 1) { - targetEdgeDescriptor.out = possiblePortsOut[0].name; - targetEdgeDescriptor.in = possiblePortsIn[0].name; - } else { - this.emit( - GRAPH_OPERATIONS.GRAPH_EDGE_ADD_DISAMBIGUATION_REQUESTED, - targetEdgeDescriptor.from.descriptor.id, - targetEdgeDescriptor.to.descriptor.id, - possiblePortsOut, - possiblePortsIn, - evt.client - ); - return; - } - } - - const edgeKey = inspectableEdgeToString(targetEdgeDescriptor); - switch (action) { - case GRAPH_OPERATIONS.GRAPH_EDGE_ATTACH: { - const existingEdge = this.#edgeGraphics.get(edgeKey); - if (existingEdge) { - break; - } - - if (evt.metaKey) { - targetEdgeDescriptor.type = InspectableEdgeType.Constant; - } - this.emit(GRAPH_OPERATIONS.GRAPH_EDGE_ATTACH, targetEdgeDescriptor); - break; - } - - case GRAPH_OPERATIONS.GRAPH_EDGE_CHANGE: { - targetEdge.overrideColor = null; - - const existingEdge = this.#edgeGraphics.get(edgeKey); - if (existingEdge) { - break; - } - - if (evt.metaKey) { - targetEdgeDescriptor.type = InspectableEdgeType.Constant; - } - this.emit( - GRAPH_OPERATIONS.GRAPH_EDGE_CHANGE, - originalEdgeDescriptor, - targetEdgeDescriptor - ); - break; - } - - default: { - // Possible ad-hoc wire disambiguation. - if (creatingAdHocEdge && targetNodePort && targetHoverNodeForAdHoc) { - const knownPorts = - targetNodePort.type === GraphNodePortType.OUT - ? possiblePortsOut - : possiblePortsIn; - - const from = - targetNodePort.type === GraphNodePortType.OUT - ? targetEdgeDescriptor.from.descriptor.id - : targetHoverNodeForAdHoc.label; - - const to = - targetNodePort.type === GraphNodePortType.IN - ? targetEdgeDescriptor.from.descriptor.id - : targetHoverNodeForAdHoc.label; - - if (knownPorts.length === 0) { - break; - } - - this.emit( - GRAPH_OPERATIONS.GRAPH_EDGE_ADD_AD_HOC_DISAMBIGUATION_REQUESTED, - from, - to, - targetNodePort.type === GraphNodePortType.OUT ? knownPorts : null, - targetNodePort.type === GraphNodePortType.IN ? knownPorts : null, - evt.client - ); - } - break; - } - } - - targetEdge.overrideColor = null; - if (targetNodePort) { - targetNodePort.overrideStatus = null; - } - - this.#removeStaleEdges(); - }; - - this.addListener("pointerup", onPointerUp); - this.addListener("pointerupoutside", onPointerUp); - } - - deselectAllChildren() { - for (const child of this.children) { - if ( - !(child instanceof GraphNode || child instanceof GraphComment) || - !child.selected - ) { - continue; - } - - child.selected = false; - } - - for (const edge of this.#edgeContainer.children) { - if (!(edge instanceof GraphEdge) || !edge.selected) { - continue; - } - - edge.selected = false; - } - - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_DESELECTED_ALL); - } - - selectAll() { - for (const child of this.children) { - if (!(child instanceof GraphNode || child instanceof GraphComment)) { - continue; - } - - child.selected = true; - } - - for (const edge of this.#edgeContainer.children) { - if (!(edge instanceof GraphEdge)) { - continue; - } - - edge.selected = true; - } - } - - selectInRect(rect: PIXI.Rectangle) { - for (const child of this.children) { - if (!(child instanceof GraphNode || child instanceof GraphComment)) { - continue; - } - - const isSelected = child.selected; - child.selected = rect.intersects(child.getBounds(true).rectangle); - if (isSelected !== child.selected) { - this.emit( - child.selected - ? GRAPH_OPERATIONS.GRAPH_NODE_SELECTED - : GRAPH_OPERATIONS.GRAPH_NODE_DESELECTED, - child.label - ); - } - } - - for (const edge of this.#edgeContainer.children) { - if (!(edge instanceof GraphEdge)) { - continue; - } - - edge.selected = rect.intersects(edge.getBounds(true).rectangle); - } - - this.#sortChildrenBySelectedStatus(); - } - - getSelectedChildren(): Array { - const selected = []; - for (const node of this.children) { - if ( - !(node instanceof GraphNode || node instanceof GraphComment) || - !node.selected - ) { - continue; - } - - selected.push(node); - } - - for (const edge of this.#edgeContainer.children) { - if (!(edge instanceof GraphEdge) || !edge.selected) { - continue; - } - - selected.push(edge); - } - - return selected; - } - - #sortChildrenBySelectedStatus() { - for (const node of this.children) { - if (!(node instanceof GraphNode || node instanceof GraphComment)) { - continue; - } - - node.zIndex = node.selected ? this.children.length - 1 : 0; - } - } - - getNodeLayoutPositions() { - return new Map(this.#layout); - } - - clearNodeLayoutPositions() { - this.#layout.clear(); - } - - getNodeLayoutPosition(node: string) { - return this.#layout.get(node); - } - - storeCommentLayoutPositions() { - for (const child of this.children) { - if (!(child instanceof GraphComment)) { - continue; - } - - this.setNodeLayoutPosition( - child.label, - "comment", - this.toGlobal(child.position), - child.expansionState, - false - ); - } - } - - setNodeLayoutPosition( - node: string, - type: "comment" | "node", - position: PIXI.PointData, - expansionState: ComponentExpansionState, - justAdded = false - ) { - this.#layout.set(node, { - ...this.toLocal(position), - type, - expansionState, - justAdded, - }); - } - - layout() { - if (!this.#edges) { - return; - } - - const g = new Dagre.graphlib.Graph(); - const opts: Partial = { - ranksep: 90, - rankdir: "LR", - align: "DR", - }; - if (this.layoutRect) { - opts.width = Math.floor(this.layoutRect.width); - opts.height = Math.floor(this.layoutRect.height); - } - - g.setGraph(opts); - g.setDefaultEdgeLabel(() => ({})); - - let nodesAdded = 0; - for (const node of this.children) { - if (!(node instanceof GraphNode)) { - continue; - } - - // Skip any nodes where the layout has already been set by the user. - if (this.#layout.has(node.id)) { - continue; - } - nodesAdded++; - g.setNode(node.id, node.dimensions); - } - - let edgesAdded = 0; - for (const edge of this.#edges) { - edgesAdded++; - g.setEdge(edge.from.descriptor.id, edge.to.descriptor.id); - } - - // Only run Dagre if there are edges & children to account for. Otherwise - // it will throw an error. - if (nodesAdded > 0 && edgesAdded > 0) { - Dagre.layout(g); - - for (const id of g.nodes()) { - const data = g.node(id); - if (!data) { - continue; - } - - const { x, y, width, height } = g.node(id); - this.#layout.set(id, { - x: Math.round(x - width / 2), - y: Math.round(y - height / 2), - type: "node", - expansionState: this.collapseNodesByDefault - ? "collapsed" - : "expanded", - }); - } - } - - // Step through any Dagre-set and custom set locations. - for (const [id, layout] of this.#layout) { - const graphNode = this.#graphNodeById.get(id); - if (!graphNode) { - continue; - } - - graphNode.position.set(layout.x, layout.y); - graphNode.expansionState = layout.expansionState; - } - - this.#drawEdges(); - } - - #setNodesCollapseState() { - for (const child of this.children) { - if (!(child instanceof GraphNode || child instanceof GraphComment)) { - continue; - } - - child.expansionState = this.collapseNodesByDefault - ? "collapsed" - : "expanded"; - } - } - - #setNodesPreviewValues() { - for (const child of this.children) { - if (!(child instanceof GraphNode)) { - continue; - } - - child.showNodePreviewValues = this.showNodePreviewValues; - } - } - - #setNodesTypeDescriptions() { - for (const child of this.children) { - if (!(child instanceof GraphNode)) { - continue; - } - - child.showNodeTypeDescriptions = this.showNodeTypeDescriptions; - } - } - - set collapseNodesByDefault(collapseNodesByDefault: boolean) { - if (collapseNodesByDefault === this.#collapseNodesByDefault) { - return; - } - - this.#isDirty = true; - this.#collapseNodesByDefault = collapseNodesByDefault; - this.#setNodesCollapseState(); - } - - get collapseNodesByDefault() { - return this.#collapseNodesByDefault; - } - - set showNodePreviewValues(showNodePreviewValues: boolean) { - if (showNodePreviewValues === this.#showNodePreviewValues) { - return; - } - - this.#isDirty = true; - this.#showNodePreviewValues = showNodePreviewValues; - this.#setNodesPreviewValues(); - } - - get showNodePreviewValues() { - return this.#showNodePreviewValues; - } - - set showNodeTypeDescriptions(showNodeTypeDescriptions: boolean) { - if (showNodeTypeDescriptions === this.#showNodeTypeDescriptions) { - return; - } - - this.#isDirty = true; - this.#showNodeTypeDescriptions = showNodeTypeDescriptions; - this.#setNodesTypeDescriptions(); - } - - get showNodeTypeDescriptions() { - return this.#showNodeTypeDescriptions; - } - - set edges(edges: InspectableEdge[] | null) { - // Validate the edges. - this.#edges = edges?.filter((edge) => edge.to && edge.from) || null; - this.#isDirty = true; - } - - get edges() { - return this.#edges; - } - - set edgeValues(edgeValues: TopGraphEdgeValues | null) { - this.#edgeValues = edgeValues; - this.#isDirty = true; - } - - get edgeValues() { - return this.#edgeValues; - } - - set nodeValues(nodeValues: TopGraphNodeActivity | null) { - this.#nodeValues = nodeValues; - this.#isDirty = true; - } - - get nodeValues() { - return this.#nodeValues; - } - - set nodes(nodes: InspectableNode[] | null) { - this.#nodes = nodes; - this.#isDirty = true; - - this.#nodeById.clear(); - if (!nodes) { - return; - } - - for (const node of nodes) { - this.#nodeById.set(node.descriptor.id, node); - } - } - - get nodes() { - return this.#nodes; - } - - set ports(ports: Map | null) { - this.#ports = ports; - this.#isDirty = true; - } - - get ports() { - return this.#ports; - } - - set comments(comments: CommentNode[] | null) { - this.#comments = comments; - this.#isDirty = true; - } - - get comments() { - return this.#comments; - } - - set highlightedNode(node: ComponentWithActivity | null) { - this.#highlightedComponent = node; - this.#drawNodeHighlight(); - } - - get highlightedNode() { - return this.#highlightedComponent; - } - - set typeMetadata(metadata: Map | null) { - this.#typeMetadata = metadata; - this.#isDirty = true; - } - - get typeMetadata() { - return this.#typeMetadata; - } - - selectEdge(edge: EdgeData) { - const edgeGraphic = this.#edgeGraphics.get(inspectableEdgeToString(edge)); - if (!edgeGraphic) { - return; - } - - this.#edgeContainer.setChildIndex( - edgeGraphic, - this.#edgeContainer.children.length - 1 - ); - - this.deselectAllChildren(); - edgeGraphic.selected = true; - } - - addToAutoSelect(item: string) { - this.#autoSelect.add(item); - } - - #edgesBetween(from: GraphNode, to: GraphNode): InspectableEdge[] { - if (!this.#edges) { - return []; - } - - const fromNode = this.#nodeById.get(from.label); - const toNode = this.#nodeById.get(to.label); - - if (!(fromNode && toNode)) { - return []; - } - - return this.#edges.filter( - (edge) => edge.from === fromNode && edge.to === toNode - ); - } - - #onChildMoved( - this: { graph: Graph; id: string }, - x: number, - y: number, - hasSettled: boolean - ) { - const position = this.graph.getNodeLayoutPosition(this.id); - const delta = { x: 0, y: 0 }; - if (position) { - delta.x = x - position.x; - delta.y = y - position.y; - } - - // Update all selected nodes. - for (const child of this.graph.getSelectedChildren()) { - if (!(child instanceof GraphNode || child instanceof GraphComment)) { - continue; - } - - const childPosition = this.graph.getNodeLayoutPosition(child.label); - if (!childPosition) { - console.log("Child has no position", child.label); - continue; - } - - const newPosition = { - x: Math.round(childPosition.x + delta.x), - y: Math.round(childPosition.y + delta.y), - }; - - this.graph.setNodeLayoutPosition( - child.label, - child instanceof GraphNode ? "node" : "comment", - this.graph.toGlobal(newPosition), - child.expansionState - ); - - if (child.label === this.id) { - continue; - } - - child.x = newPosition.x; - child.y = newPosition.y; - } - - this.graph.#drawEdges(); - this.graph.#drawNodeHighlight(); - - if (!hasSettled) { - return; - } - - // Propagate the move event out to the graph renderer when the cursor is released. - const locations: Array<{ - id: string; - type: "node" | "comment"; - x: number; - y: number; - expansionState: ComponentExpansionState; - }> = []; - for (const child of this.graph.getSelectedChildren()) { - if (!(child instanceof GraphNode || child instanceof GraphComment)) { - continue; - } - - locations.push({ - id: child.label, - type: child instanceof GraphNode ? "node" : "comment", - x: child.position.x, - y: child.position.y, - expansionState: child.expansionState, - }); - } - - this.graph.emit(GRAPH_OPERATIONS.GRAPH_NODES_MOVED, locations); - } - - #performAutoSelect() { - for (const graphEdge of this.#edgeContainer.children) { - if (!(graphEdge instanceof GraphEdge)) { - continue; - } - - if (!graphEdge.edge) { - continue; - } - - const edgeDescriptor = inspectableEdgeToString(graphEdge.edge); - if (this.#autoSelect.has(edgeDescriptor)) { - graphEdge.selected = true; - this.#autoSelect.delete(edgeDescriptor); - } - } - - for (const graphNode of this.children) { - if ( - !(graphNode instanceof GraphNode || graphNode instanceof GraphComment) - ) { - continue; - } - - if (this.#autoSelect.has(graphNode.label)) { - graphNode.selected = true; - this.#autoSelect.delete(graphNode.label); - } - } - - this.emit(GRAPH_OPERATIONS.GRAPH_AUTOSELECTED_NODES); - } - - #drawNodeHighlight() { - if (!this.#graphNodeById) { - return; - } - - if (!this.#highlightedComponent) { - this.#highlightedNode.clear(); - return; - } - - const graphNode = this.#graphNodeById.get( - this.#highlightedComponent.descriptor.id - ); - if (!graphNode || !(graphNode instanceof GraphNode)) { - this.#highlightedNode.clear(); - return; - } - - const renderNodeHighlight = () => { - if (graphNode.width === 0 || graphNode.height === 0) { - return; - } - - const { width, height } = graphNode.dimensions; - this.#highlightedNode.clear(); - this.#highlightedNode.setFillStyle({ - color: this.#highlightedNodeColor, - alpha: 0.25, - }); - this.#highlightedNode.beginPath(); - this.#highlightedNode.roundRect( - graphNode.x - this.#highlightPadding, - graphNode.y - this.#highlightPadding, - width + this.#highlightPadding * 2, - height + this.#highlightPadding * 2, - graphNode.borderRadius + this.#highlightPadding - ); - this.#highlightedNode.closePath(); - this.#highlightedNode.fill(); - - this.addChildAt(this.#highlightedNode, 0); - }; - - // It's possible this will be called before the graph node has rendered, so - // if that happens wait for the draw event to fire then try again. - if (graphNode.width === 0 && graphNode.height === 0) { - graphNode.once(GRAPH_OPERATIONS.GRAPH_NODE_DRAWN, renderNodeHighlight); - } else { - renderNodeHighlight(); - } - } - - #drawNodes() { - if (!this.#nodes || !this.#ports) { - return; - } - - const isInitialDraw = this.#isInitialDraw; - this.#isInitialDraw = false; - - /** - * We only position the graph on the initial draw, and we need the graph to - * be drawn before we can query its dimensions. So we check the layout map, - * which should only be empty on the first render. We then track each node - * render, and when all have drawn we notify the graph itself that it can - * centralize the graph. - */ - let nodesLeftToDraw = this.#nodes.length; - const onDraw = function (this: { - graphNode: GraphNode; - layout: LayoutInfo | null; - isInitialDraw: boolean; - }) { - nodesLeftToDraw--; - - // Freshly added nodes are auto-selected and repositioned to the middle - // of the drop location. - if (this.layout && this.layout.justAdded) { - this.layout.x -= this.graphNode.width / 2; - this.layout.y -= this.graphNode.height / 2; - this.layout.justAdded = false; - - this.graphNode.selected = true; - this.graphNode.position.set(this.layout.x, this.layout.y); - this.graphNode.expansionState = this.layout.expansionState; - - this.graphNode.parent.emit( - GRAPH_OPERATIONS.GRAPH_NODE_SELECTED, - this.graphNode.label - ); - this.graphNode.emit( - GRAPH_OPERATIONS.GRAPH_NODE_MOVED, - this.layout.x, - this.layout.y, - true - ); - } - - if (nodesLeftToDraw === 0) { - this.graphNode.parent.emit(GRAPH_OPERATIONS.GRAPH_DRAW); - - if (this.isInitialDraw) { - this.graphNode.parent.emit(GRAPH_OPERATIONS.GRAPH_INITIAL_DRAW); - } - } - }; - - for (const node of this.#nodes) { - const { id, type } = node.descriptor; - const { title: typeTitle = type, icon } = - this.#typeMetadata?.get(type) || {}; - let graphNode = this.#graphNodeById.get(id); - if (!graphNode || !(graphNode instanceof GraphNode)) { - graphNode = new GraphNode(id, type, node.title(), typeTitle); - graphNode.showNodeTypeDescriptions = this.showNodeTypeDescriptions; - graphNode.showNodePreviewValues = this.showNodePreviewValues; - - const colors = nodeColors.get(type) || defaultNodeColors; - graphNode.titleTextColor = colors.text; - graphNode.borderColor = colors.border; - - this.#graphNodeById.set(id, graphNode); - } - - if (graphNode.title !== node.title()) { - graphNode.title = node.title(); - } - - if (icon && GraphAssets.instance().has(icon)) { - graphNode.icon = icon; - } else { - const icon = nodeIcons.get(type); - if (icon) { - graphNode.icon = icon.name; - } - } - - if (node.descriptor.metadata?.visual) { - const { x, y, collapsed } = node.descriptor.metadata - .visual as VisualMetadata; - - // We may receive visual values for the node, but we may also have - // marked the node as having just been added to the editor. So we go - // looking for the layout value in order to honour the `justAdded` flag - // that may have been set. - const existingLayout = this.getNodeLayoutPosition(id); - let justAdded = false; - if (existingLayout) { - justAdded = existingLayout.justAdded || false; - } - const expansionState = expansionStateFromMetadata( - collapsed, - this.collapseNodesByDefault - ); - const pos = this.toGlobal({ x: x ?? 0, y: y ?? 0 }); - this.setNodeLayoutPosition(id, "node", pos, expansionState, justAdded); - - graphNode.expansionState = expansionState; - } - - const portInfo = this.#ports.get(id); - if (!portInfo) { - console.warn(`Unable to locate port info for ${id}`); - continue; - } - - graphNode.label = id; - graphNode.readOnly = this.readOnly; - graphNode.inPorts = portInfo.inputs.ports; - graphNode.outPorts = portInfo.outputs.ports; - graphNode.fixedInputs = portInfo.inputs.fixed; - graphNode.fixedOutputs = portInfo.outputs.fixed; - graphNode.activity = this.#nodeValues?.get(id) ?? null; - - graphNode.forceUpdateDimensions(); - graphNode.removeAllListeners(); - graphNode.addPointerEventListeners(); - graphNode.on(GRAPH_OPERATIONS.GRAPH_NODE_MOVED, this.#onChildMoved, { - graph: this, - id, - }); - - // PIXI doesn't bubble events automatically, so we re-issue the event for - // requesting the menu to the graph renderer. - graphNode.on( - GRAPH_OPERATIONS.GRAPH_NODE_MENU_REQUESTED, - (graphNode: GraphNode, location: PIXI.ObservablePoint) => { - this.emit( - GRAPH_OPERATIONS.GRAPH_NODE_MENU_REQUESTED, - graphNode, - location - ); - } - ); - - graphNode.once(GRAPH_OPERATIONS.GRAPH_NODE_DRAWN, onDraw, { - graphNode, - layout: this.#layout.get(id) || null, - isInitialDraw, - }); - - graphNode.on(GRAPH_OPERATIONS.GRAPH_NODE_EXPAND_COLLAPSE, () => { - this.#redrawAllEdges(); - this.#drawNodeHighlight(); - - const layout = this.#layout.get(graphNode.label); - if (!layout) { - return; - } - - if (layout.expansionState === graphNode.expansionState) { - return; - } - - layout.expansionState = graphNode.expansionState; - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_EXPAND_COLLAPSE); - }); - - graphNode.on( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_MOUSEENTER, - (...args: unknown[]) => - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_PORT_MOUSEENTER, ...args) - ); - - graphNode.on( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_MOUSELEAVE, - (...args: unknown[]) => - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_PORT_MOUSELEAVE, ...args) - ); - - graphNode.on( - GRAPH_OPERATIONS.GRAPH_NODE_PORT_VALUE_EDIT, - (...args: unknown[]) => { - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_PORT_VALUE_EDIT, ...args); - } - ); - - graphNode.on( - GRAPH_OPERATIONS.GRAPH_NODE_ACTIVITY_SELECTED, - (...args: unknown[]) => { - this.emit(GRAPH_OPERATIONS.GRAPH_NODE_ACTIVITY_SELECTED, ...args); - } - ); - - graphNode.on( - GRAPH_OPERATIONS.GRAPH_SHOW_TOOLTIP, - (...args: unknown[]) => { - this.emit(GRAPH_OPERATIONS.GRAPH_SHOW_TOOLTIP, ...args); - } - ); - - graphNode.on( - GRAPH_OPERATIONS.GRAPH_HIDE_TOOLTIP, - (...args: unknown[]) => { - this.emit(GRAPH_OPERATIONS.GRAPH_HIDE_TOOLTIP, ...args); - } - ); - - this.addChild(graphNode); - } - - this.#removeStaleNodes(); - } - - // TODO: Merge this with below. - #createTemporaryEdge(edge: EdgeData): GraphEdge | null { - const fromNode = this.#graphNodeById.get(edge.from.descriptor.id); - const toNode = this.#graphNodeById.get(edge.to.descriptor.id); - - if (!(fromNode && toNode)) { - return null; - } - - if (!(fromNode instanceof GraphNode && toNode instanceof GraphNode)) { - return null; - } - - const edgeGraphic = new GraphEdge(fromNode, toNode, true); - edgeGraphic.edge = edge; - this.#edgeGraphics.set("__Temporary_Edge", edgeGraphic); - this.#edgeContainer.addChild(edgeGraphic); - - return edgeGraphic; - } - - #redrawAllEdges() { - if (!this.#edges) { - return; - } - - for (const edge of this.#edges) { - const edgeGraphic = this.#edgeGraphics.get(inspectableEdgeToString(edge)); - if (!edgeGraphic) { - continue; - } - - edgeGraphic.forceRedraw(); - } - } - - #drawComments() { - if (!this.#comments) { - return; - } - - for (const node of this.#comments) { - const { id, text } = node; - let graphComment = this.#graphNodeById.get(id); - if (!graphComment) { - graphComment = new GraphComment(); - - this.#graphNodeById.set(id, graphComment); - } - - if (!(graphComment instanceof GraphComment)) { - continue; - } - - if (node.metadata?.visual) { - const { x, y, collapsed } = node.metadata.visual as VisualMetadata; - - // We may receive visual values for the node, but we may also have - // marked the node as having just been added to the editor. So we go - // looking for the layout value in order to honour the `justAdded` flag - // that may have been set. - const existingLayout = this.getNodeLayoutPosition(id); - let justAdded = false; - if (existingLayout) { - justAdded = existingLayout.justAdded || false; - } - const expansionState = expansionStateFromMetadata( - collapsed, - this.collapseNodesByDefault - ); - - const pos = this.toGlobal({ x, y }); - this.setNodeLayoutPosition( - id, - "comment", - pos, - expansionState, - justAdded - ); - - graphComment.expansionState = expansionState; - } - - graphComment.label = id; - graphComment.text = text; - graphComment.readOnly = this.readOnly; - graphComment.removeAllListeners(); - graphComment.addPointerEventListeners(); - graphComment.on(GRAPH_OPERATIONS.GRAPH_NODE_MOVED, this.#onChildMoved, { - graph: this, - id, - }); - - graphComment.on( - GRAPH_OPERATIONS.GRAPH_BOARD_LINK_CLICKED, - (board: string) => { - // Re-emit for the renderer to pick up. - this.emit(GRAPH_OPERATIONS.GRAPH_BOARD_LINK_CLICKED, board); - } - ); - - graphComment.on( - GRAPH_OPERATIONS.GRAPH_COMMENT_EDIT_REQUESTED, - (...args: unknown[]) => { - this.emit(GRAPH_OPERATIONS.GRAPH_COMMENT_EDIT_REQUESTED, ...args); - } - ); - - graphComment.once(GRAPH_OPERATIONS.GRAPH_COMMENT_DRAWN, () => { - const layout = this.getNodeLayoutPosition(id); - - if (!layout || !layout.justAdded) { - return; - } - - layout.x -= graphComment.width / 2; - layout.y -= graphComment.height / 2; - layout.justAdded = false; - - graphComment.position.set(layout.x, layout.y); - graphComment.emit( - GRAPH_OPERATIONS.GRAPH_NODE_MOVED, - layout.x, - layout.y, - true - ); - }); - - this.addChild(graphComment); - } - - this.#removeStaleNodes(); - } - - #drawEdges() { - if (!this.#edges) { - return; - } - - for (const edge of this.#edges) { - let edgeGraphic = this.#edgeGraphics.get(inspectableEdgeToString(edge)); - if (!edgeGraphic) { - const fromNode = this.#graphNodeById.get(edge.from.descriptor.id); - const toNode = this.#graphNodeById.get(edge.to.descriptor.id); - - // Only create the edge when the nodes are present. - if (!(fromNode && toNode)) { - continue; - } - - if (!(fromNode instanceof GraphNode && toNode instanceof GraphNode)) { - return null; - } - - edgeGraphic = new GraphEdge(fromNode, toNode); - edgeGraphic.type = edge.type; - - // Propagate edge value clicks to the graph renderer. - edgeGraphic.on( - GRAPH_OPERATIONS.GRAPH_EDGE_VALUE_SELECTED, - (...args: unknown[]) => { - this.emit(GRAPH_OPERATIONS.GRAPH_EDGE_VALUE_SELECTED, ...args); - } - ); - - this.#edgeGraphics.set(inspectableEdgeToString(edge), edgeGraphic); - this.#edgeContainer.addChild(edgeGraphic); - } - - edgeGraphic.value = this.#edgeValues?.get(edge) ?? null; - edge.inPort().then((port) => { - edgeGraphic.schema = port.schema || null; - }); - edgeGraphic.edge = edge; - edgeGraphic.readOnly = this.readOnly; - if (this.highlightInvalidWires) { - this.#scheduleValidation(edge, edgeGraphic); - } else { - edgeGraphic.invalid = false; - } - } - - this.#removeStaleEdges(); - - this.addChildAt(this.#edgeContainer, 0); - } - - /** - * Validation is asynchronous because it relies on calling `describe` to get - * node descriptions, and `describe` functions are asynchronous. - */ - async #scheduleValidation(edge: InspectableEdge, edgeGraphic: GraphEdge) { - // A unique symbol to act as a token representing this particular request. - const thisRequest = Symbol(); - this.#latestPendingValidateRequest.set(edgeGraphic, thisRequest); - const result = await edge.validate(); - if (this.#latestPendingValidateRequest.get(edgeGraphic) !== thisRequest) { - // Another validate request started before this one finished. Cancel this - // one, otherwise we might clobber a newer result with an older one, since - // the timing of validation is not guaranteed. - return; - } - this.#latestPendingValidateRequest.delete(edgeGraphic); - edgeGraphic.invalid = result.status === "invalid"; - } - - #removeStaleEdges() { - if (!this.#edges) { - return; - } - - // If there's a mismatch of sizes it likely means an edge has been removed - // so find that edge and dispose of it. - if (this.#edgeGraphics.size === this.#edges.length) { - return; - } - - for (const [edgeDescription, edgeGraphic] of this.#edgeGraphics) { - if ( - this.#edges.find( - (edge) => inspectableEdgeToString(edge) === edgeDescription - ) - ) { - continue; - } - - edgeGraphic.removeFromParent(); - edgeGraphic.destroy(); - this.#edgeGraphics.delete(edgeDescription); - } - } - - #removeStaleNodes() { - const count = (this.#comments?.length || 0) + (this.#nodes?.length || 0); - if (count < this.#graphNodeById.size) { - for (const [id, node] of this.#graphNodeById) { - const commentNode = this.#comments?.find((node) => node.id === id); - const graphNode = this.#nodes?.find( - (node) => node.descriptor.id === id - ); - if (commentNode || graphNode) { - continue; - } - - node.removeFromParent(); - node.destroy(); - this.#graphNodeById.delete(id); - this.#layout.delete(id); - } - } - } -} diff --git a/packages/shared-ui/src/elements/editor/node-selector.ts b/packages/shared-ui/src/elements/editor/node-selector.ts deleted file mode 100644 index 92c32a9663b..00000000000 --- a/packages/shared-ui/src/elements/editor/node-selector.ts +++ /dev/null @@ -1,442 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - InspectableGraph, - InspectableKit, - NodeHandlerMetadata, -} from "@google-labs/breadboard"; -import { LitElement, html, css, nothing } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import { map } from "lit/directives/map.js"; -import { classMap } from "lit/directives/class-map.js"; -import { Ref, createRef, ref } from "lit/directives/ref.js"; -import { KitNodeChosenEvent } from "../../events/events.js"; -import { Task } from "@lit/task"; - -const DATA_TYPE = "text/plain"; - -@customElement("bb-node-selector") -export class NodeSelector extends LitElement { - @property() - graph: InspectableGraph | null = null; - - @state() - filter: string | null = null; - - @property() - showExperimentalComponents = false; - - #searchInputRef: Ref = createRef(); - #listRef: Ref = createRef(); - #lastSelectedId: string | null = null; - #kitInfoTask = new Task(this, { - task: async () => { - return this.#createKitList(this.graph?.kits() || []); - }, - args: () => [this.graph?.kits() || []], - }); - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: grid; - background: #ededed; - border-radius: 12px; - box-shadow: - 0px 1px 2px rgba(0, 0, 0, 0.3), - 0px 1px 3px 1px rgba(0, 0, 0, 0.15); - padding: 8px; - - --border-radius: 32px; - --kit-height: 24px; - --kit-margin: 1px; - --kit-count: 2; - --height: calc(var(--kit-count) * (var(--kit-height))); - } - - #container { - display: grid; - } - - #search { - margin-bottom: 8px; - border-radius: 8px; - border: none; - height: 24px; - padding-left: 24px; - background: #fff var(--bb-icon-search) 4px center no-repeat; - background-size: 16px 16px; - } - - #kit-list { - padding: 0; - margin: 0; - display: flex; - flex-direction: column; - list-style: none; - font-size: var(--bb-text-small); - color: #222; - height: var(--height); - position: relative; - width: min(80vw, 360px); - } - - #kit-list > li { - width: 40%; - } - - input[type="radio"] { - display: none; - } - - label { - height: var(--kit-height); - display: block; - border-radius: var(--border-radius) 0 0 var(--border-radius); - padding: 0 12px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - position: relative; - cursor: pointer; - line-height: var(--kit-height); - color: #1a1a1a; - } - - li.kit-item .node-id { - white-space: nowrap; - height: var(--kit-height); - line-height: var(--kit-height); - font: 600 var(--bb-label-medium) / var(--bb-label-line-height-medium) - var(--bb-font-family); - } - - li.kit-item .node-description { - font: 400 var(--bb-label-small) / var(--bb-label-line-height-small) - var(--bb-font-family); - } - - #kit-list li:hover label::before { - content: ""; - background: #000; - position: absolute; - left: 1px; - top: 1px; - bottom: 1px; - right: 8px; - border-radius: var(--bb-grid-size-12); - z-index: 0; - opacity: 0.1; - } - - #kit-list li:hover label span { - position: relative; - z-index: 1; - } - - label { - opacity: 0.5; - } - - input[type="radio"]:checked ~ label { - background: #fff; - border-radius: var(--border-radius) 0 0 var(--border-radius); - position: relative; - opacity: 1; - } - - input[type="radio"]:checked ~ label::before { - display: none; - } - - input[type="radio"] ~ .kit-contents { - display: none; - } - - input[type="radio"]:checked ~ .kit-contents { - display: block; - position: absolute; - left: 40%; - top: 0; - height: var(--height); - overflow-y: scroll; - scrollbar-gutter: stable; - background: #fff; - margin: 0; - width: 60%; - border-radius: 8px; - } - - .kit-contents ul { - display: block; - } - - #kit-list - li:first-of-type:last-of-type - input[type="radio"]:checked - ~ .kit-contents, - #kit-list li:first-of-type input[type="radio"]:checked ~ .kit-contents { - border-radius: 0 8px 8px 8px; - } - - #kit-list li:last-of-type input[type="radio"]:checked ~ .kit-contents { - border-radius: 8px 8px 8px 0; - } - - .kit-contents ul { - padding: 0; - margin: 0; - } - - li.kit-item { - margin: var(--bb-grid-size) 0; - padding: var(--bb-grid-size-2) var(--bb-grid-size-4); - width: 100%; - border-radius: 12px; - position: relative; - background: #fff; - cursor: grab; - } - - li.kit-item:hover::before { - content: ""; - background: #000; - position: absolute; - left: var(--bb-grid-size-2); - top: 1px; - bottom: 1px; - right: var(--bb-grid-size-2); - border-radius: var(--bb-grid-size); - z-index: 0; - opacity: 0.05; - } - - li.kit-item:active { - cursor: grabbing; - } - - li.kit-item span { - position: relative; - z-index: 1; - } - `; - - selectSearchInput() { - if (!this.#searchInputRef.value) { - return; - } - - this.#searchInputRef.value.select(); - } - - updated() { - if (!this.#listRef.value) { - return; - } - - if (this.#listRef.value.querySelector("input[checked]")) { - return; - } - - if (this.#lastSelectedId) { - const lastInput = this.#listRef.value.querySelector( - `#${this.#lastSelectedId}` - ) as HTMLInputElement; - if (lastInput) { - lastInput.checked = true; - return; - } - } - - const firstInput = this.#listRef.value.querySelector("input"); - if (!firstInput) { - return; - } - - firstInput.checked = true; - } - - async #createKitList(kits: InspectableKit[]) { - const kitList = new Map< - string, - { id: string; metadata: NodeHandlerMetadata }[] - >(); - kits.sort((kit1, kit2) => - (kit1.descriptor.title || "") > (kit2.descriptor.title || "") ? 1 : -1 - ); - - for (const kit of kits) { - if (!kit.descriptor.title) { - continue; - } - - if (kit.descriptor.tags?.includes("deprecated")) { - continue; - } - - if ( - !this.showExperimentalComponents && - kit.descriptor.tags?.includes("experimental") - ) { - continue; - } - - const typeMetadata = ( - await Promise.all( - kit.nodeTypes.map(async (node) => { - const metadata = await node.metadata(); - if ( - !this.showExperimentalComponents && - metadata.tags?.includes("experimental") - ) { - return null; - } - return { id: node.type(), metadata: await node.metadata() }; - }) - ) - ).filter(Boolean) as { id: string; metadata: NodeHandlerMetadata }[]; - - const available = typeMetadata.filter( - ({ metadata }) => !metadata.deprecated - ); - - if (available.length === 0) { - continue; - } - - kitList.set(kit.descriptor.title, available); - } - return kitList; - } - - #filterKitList( - kitList: Map - ) { - if (!this.filter) { - return kitList; - } - - const filteredKitList = new Map< - string, - { id: string; metadata: NodeHandlerMetadata }[] - >(); - - const filter = new RegExp(this.filter, "gim"); - - for (const [kitName, kitContents] of kitList) { - const filteredKitContents = kitContents.filter( - (nodeTypeInfo) => - filter.test(nodeTypeInfo.id) || - (nodeTypeInfo.metadata.title && - filter.test(nodeTypeInfo.metadata.title)) - ); - - if (filteredKitContents.length > 0) { - filteredKitList.set(kitName, filteredKitContents); - } - } - - return filteredKitList; - } - - render() { - if (!this.graph) { - return nothing; - } - - const kits = this.graph.kits() || []; - - this.style.setProperty("--kit-count", kits.length.toString()); - - return this.#kitInfoTask.render({ - pending: () => html`
    Loading...
    `, - complete: (kitList) => { - kitList = this.#filterKitList(kitList); - - return html`
    evt.stopPropagation()} - > - { - if (!(evt.target instanceof HTMLInputElement)) { - return; - } - - this.filter = evt.target.value; - }} - /> -
    -
      - ${map(kitList, ([kitName, kitContents]) => { - const kitId = kitName.toLocaleLowerCase().replace(/\W/gim, "-"); - return html`
    • - { - if (!(evt.target instanceof HTMLElement)) { - return; - } - - this.#lastSelectedId = evt.target.id; - }} - /> -
      -
        - ${map(kitContents, (nodeTypeInfo) => { - const className = nodeTypeInfo.id - .toLocaleLowerCase() - .replaceAll(/\W/gim, "-"); - const id = nodeTypeInfo.id; - const description = nodeTypeInfo.metadata.description; - const title = nodeTypeInfo.metadata.title || id; - return html`
      • { - this.dispatchEvent(new KitNodeChosenEvent(id)); - }} - @dragstart=${(evt: DragEvent) => { - if (!evt.dataTransfer) { - return; - } - evt.dataTransfer.setData(DATA_TYPE, id); - }} - > -
        ${title}
        - ${description - ? html`
        - ${description} -
        ` - : nothing} -
      • `; - })} -
      -
      -
    • `; - })} -
    -
    -
    -
    `; - }, - }); - } -} diff --git a/packages/shared-ui/src/elements/editor/port-tooltip.ts b/packages/shared-ui/src/elements/editor/port-tooltip.ts deleted file mode 100644 index 7596320155b..00000000000 --- a/packages/shared-ui/src/elements/editor/port-tooltip.ts +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { ValidateResult, type InspectablePort } from "@google-labs/breadboard"; -import { LitElement, css, html, nothing } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import "./fancy-json.js"; - -@customElement("bb-port-tooltip") -export class PortTooltip extends LitElement { - #port?: InspectablePort; - #latestValidateRequest?: symbol; - - @property({ reflect: false, type: Object }) - get port(): InspectablePort | undefined { - return this.#port; - } - - set port(port: InspectablePort | undefined) { - this.#port = port; - this.#latestValidateRequest = undefined; - this._validation = undefined; - if (port === undefined) { - return; - } - const firstWire = port.edges[0]; - if (firstWire === undefined) { - return; - } - const thisRequest = Symbol(); - this.#latestValidateRequest = thisRequest; - firstWire.validate().then((validation) => { - if (thisRequest === this.#latestValidateRequest) { - this._validation = validation; - this.#latestValidateRequest = undefined; - } - }); - } - - @state() - private _validation?: ValidateResult; - - static styles = css` - pre { - font-size: 12px; - padding: 2px 12px; - width: 350px; - } - bb-fancy-json::part(error) { - text-decoration: wavy red underline; - } - `; - - override render() { - if (!this.port) { - return nothing; - } - const info = { - name: this.port.name, - title: this.port.title, - status: this.port.status, - configured: this.port.configured, - schema: this.port.schema, - }; - const annotations = []; - if (this._validation?.status === "invalid") { - const firstError = this._validation.errors[0]; - if (firstError.detail) { - const path = - this.port.kind === "output" - ? firstError.detail.outputPath - : firstError.detail.inputPath; - annotations.push({ path: ["schema", ...path], partName: "error" }); - } - } - return html`
    `; - } -} diff --git a/packages/shared-ui/src/elements/editor/types.ts b/packages/shared-ui/src/elements/editor/types.ts deleted file mode 100644 index f3bd1a4a918..00000000000 --- a/packages/shared-ui/src/elements/editor/types.ts +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export enum GRAPH_OPERATIONS { - GRAPH_BOARD_LINK_CLICKED = "graphboardlinkclicked", - GRAPH_AUTOSELECTED_NODES = "graphautoselectednodes", - GRAPH_NODE_DRAWN = "graphnodedrawn", - GRAPH_COMMENT_DRAWN = "graphcommentdrawn", - GRAPH_COMMENT_EDIT_REQUESTED = "graphcommenteditrequested", - GRAPH_NODE_MOVED = "graphnodemoved", - GRAPH_NODES_MOVED = "graphnodesmoved", - GRAPH_INITIAL_DRAW = "graphinitialdraw", - GRAPH_DRAW = "graphdraw", - GRAPH_NODE_SELECTED = "graphnodeselected", - GRAPH_NODE_DESELECTED = "graphnodedeselected", - GRAPH_NODE_DESELECTED_ALL = "graphnodedeselectedall", - GRAPH_NODE_ACTIVITY_SELECTED = "graphnodeactivityselected", - GRAPH_EDGE_VALUE_SELECTED = "graphedgevalueselected", - GRAPH_EDGE_ATTACH = "graphedgeattach", - GRAPH_EDGE_DETACH = "graphedgedetach", - GRAPH_EDGE_CHANGE = "graphedgechange", - GRAPH_EDGE_SELECT_DISAMBIGUATION_REQUESTED = "graphedgeselectdisambiguationrequested", - GRAPH_EDGE_ADD_DISAMBIGUATION_REQUESTED = "graphedgeadddisambiguationrequested", - GRAPH_EDGE_ADD_AD_HOC_DISAMBIGUATION_REQUESTED = "graphedgeaddadhocdisambiguationrequested", - GRAPH_NODE_EXPAND_COLLAPSE = "graphnodeexpandcollapse", - GRAPH_NODE_MENU_CLICKED = "graphnodemenuclicked", - GRAPH_NODE_MENU_REQUESTED = "graphnodemenurequested", - GRAPH_NODE_PORT_MOUSEENTER = "graphnodeportmouseenter", - GRAPH_NODE_PORT_MOUSELEAVE = "graphnodeportmouseleave", - GRAPH_NODE_PORT_VALUE_EDIT = "graphnodeportvalueedit", - GRAPH_SHOW_TOOLTIP = "graphshowtooltip", - GRAPH_HIDE_TOOLTIP = "graphhidetooltip", -} - -export enum GraphNodePortType { - IN = "in", - OUT = "out", - INERT = "inert", -} - -export type ComponentExpansionState = "collapsed" | "expanded" | "advanced"; - -export type LayoutInfo = { - x: number; - y: number; - type: "comment" | "node"; - expansionState: ComponentExpansionState; - justAdded?: boolean; -}; - -export type VisualMetadata = { - x: number; - y: number; - collapsed: ComponentExpansionState | boolean; -}; diff --git a/packages/shared-ui/src/elements/editor/utils.ts b/packages/shared-ui/src/elements/editor/utils.ts deleted file mode 100644 index a130c232845..00000000000 --- a/packages/shared-ui/src/elements/editor/utils.ts +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { InspectableEdgeType, InspectablePort } from "@google-labs/breadboard"; -import type { EdgeData } from "../../types/types.js"; -import { ComponentExpansionState, VisualMetadata } from "./types.js"; - -const documentStyles = getComputedStyle(document.documentElement); - -type ValidColorStrings = `#${number}` | `--${string}`; - -export function getGlobalColor( - name: ValidColorStrings, - defaultValue: ValidColorStrings = "#333333" -) { - const value = documentStyles.getPropertyValue(name)?.replace(/^#/, ""); - const valueAsNumber = parseInt(value || defaultValue, 16); - if (Number.isNaN(valueAsNumber)) { - return 0xff00ff; - } - return valueAsNumber; -} - -export function inspectableEdgeToString(edge: EdgeData): string { - return `${edge.from.descriptor.id}:${edge.out}->${edge.to.descriptor.id}:${edge.in}`; -} - -export function edgeToString(edge: { - from: string; - to: string; - out: string; - in: string; -}): string { - const fakeEdge = { - from: { - descriptor: { - id: edge.from, - }, - }, - to: { - descriptor: { - id: edge.to, - }, - }, - out: edge.out, - in: edge.in, - type: InspectableEdgeType.Ordinary, - }; - return inspectableEdgeToString(fakeEdge); -} - -export const DBL_CLICK_DELTA = 450; - -export function isConfigurablePort( - port: InspectablePort, - expansionState: ComponentExpansionState = "expanded" -): boolean { - if (port.star) return false; - if (port.name === "") return false; - - if (expansionState === "advanced") return true; - - if (port.schema.behavior?.includes("config")) return true; - const items = port.schema.items; - if (items && !Array.isArray(items) && items.behavior?.includes("config")) { - return true; - } - - return false; -} - -export function computeNextExpansionState( - state: ComponentExpansionState -): ComponentExpansionState { - switch (state) { - case "expanded": - return "advanced"; - case "collapsed": - return "expanded"; - case "advanced": - return "collapsed"; - default: - return "expanded"; - } -} - -export function expansionStateFromMetadata( - collapsed: VisualMetadata["collapsed"], - collapseNodesByDefault: boolean -): ComponentExpansionState { - if (typeof collapsed === "boolean") { - return collapsed ? "collapsed" : "expanded"; - } else { - return collapsed ?? (collapseNodesByDefault ? "collapsed" : "expanded"); - } -} diff --git a/packages/shared-ui/src/elements/elements.ts b/packages/shared-ui/src/elements/elements.ts deleted file mode 100644 index 5da873bb3ef..00000000000 --- a/packages/shared-ui/src/elements/elements.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -export { ActivityLog } from "./activity-log/activity-log.js"; -export { ActivityLogLite } from "./activity-log/activity-log-lite.js"; -export { ArrayEditor } from "./input/array/array-editor.js"; -export { BoardDetails } from "./board-details/board-details.js"; -export { BoardActivityOverlay } from "./overlay/board-activity.js"; -export { BoardEditOverlay } from "./overlay/board-edit.js"; -export { BoardSelector } from "./input/board-selector/board-selector.js"; -export { CodeEditor } from "./input/code-editor/code-editor.js"; -export { ConnectionBroker } from "./connection/connection-broker.js"; -export { ConnectionInput } from "./connection/connection-input.js"; -export { ConnectionSettings } from "./connection/connection-settings.js"; -export { ConnectionSignin } from "./connection/connection-signin.js"; -export { CommentOverlay } from "./overlay/comment.js"; -export { DrawableInput } from "./input/drawable/drawable.js"; -export { EdgeValueOverlay } from "./overlay/edge-value.js"; -export { Editor } from "./editor/editor.js"; -export { EventDetails } from "./event-details/event-details.js"; -export { FancyJson } from "./editor/fancy-json.js"; -export { FirstRunOverlay } from "./overlay/first-run.js"; -export { GoogleDriveFileId } from "./google-drive/google-drive-file-id.js"; -export { GoogleDriveQuery } from "./google-drive/google-drive-query.js"; -export { GraphHistory } from "./graph-history/graph-history.js"; -export { GraphRenderer } from "./editor/graph-renderer.js"; -export { JSONTree } from "./json-tree/json-tree.js"; -export { LLMInput } from "./input/llm-input/llm-input.js"; -export { LLMInputArray } from "./input/llm-input/llm-input-array.js"; -export { LLMOutput } from "./llm-output/llm-output.js"; -export { LLMOutputArray } from "./llm-output/llm-output-array.js"; -export { Navigation } from "./nav/nav.js"; -export { NodeConfigurationOverlay } from "./overlay/node-configurator.js"; -export { NodeMetaDetails } from "./node-info/node-meta-details.js"; -export { NodeConfigurationInfo } from "./node-info/node-configuration.js"; -export { NodeRunner } from "./node-runner/node-runner.js"; -export { NodeSelector } from "./editor/node-selector.js"; -export { OverflowMenu } from "./overflow-menu/overflow-menu.js"; -export { Overlay } from "./overlay/overlay.js"; -export { PortTooltip } from "./editor/port-tooltip.js"; -export { ProviderOverlay } from "./overlay/provider.js"; -export { SaveAsOverlay } from "./overlay/save-as.js"; -export { SchemaEditor } from "./input/schema-editor/schema-editor.js"; -export { SettingsEditOverlay } from "./overlay/settings-edit.js"; -export { Splitter } from "./splitter/splitter.js"; -export { Switcher } from "./switcher/switcher.js"; -export { Toast } from "./toast/toast.js"; -export { Tooltip } from "./tooltip/tooltip.js"; -export { UI } from "./ui-controller/ui-controller.js"; -export { UserInput } from "./input/user-input.js"; -export { WebcamInput } from "./input/webcam/webcam.js"; -export { WelcomePanel } from "./welcome-panel/welcome-panel.js"; - -export { googleDriveFileIdInputPlugin } from "./google-drive/google-drive-file-id.js"; -export { googleDriveQueryInputPlugin } from "./google-drive/google-drive-query.js"; -export { TokenVendor, tokenVendorContext } from "./connection/token-vendor.js"; diff --git a/packages/shared-ui/src/elements/event-details/event-details.ts b/packages/shared-ui/src/elements/event-details/event-details.ts deleted file mode 100644 index 648c26161ec..00000000000 --- a/packages/shared-ui/src/elements/event-details/event-details.ts +++ /dev/null @@ -1,147 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { - InspectablePort, - InspectableRunEvent, - isLLMContent, - isLLMContentArray, - OutputValues, -} from "@google-labs/breadboard"; -import { LitElement, html, css, nothing, HTMLTemplateResult } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { until } from "lit/directives/until.js"; -import { markdown } from "../../directives/markdown.js"; -import { classMap } from "lit/directives/class-map.js"; - -@customElement("bb-event-details") -export class EventDetails extends LitElement { - @property() - event: InspectableRunEvent | null = null; - - static styles = css` - :host { - display: block; - } - - .item { - margin-bottom: var(--bb-grid-size-2); - } - - .item h1 { - font: 400 var(--bb-label-large) / var(--bb-label-line-height-large) - var(--bb-font-family); - margin: var(--bb-grid-size) 0; - } - - .item .value { - font: 400 var(--bb-label-medium) / var(--bb-label-line-height-medium) - var(--bb-font-family-mono); - color: var(--bb-inputs-700); - } - `; - - #isImageURL(nodeValue: unknown): nodeValue is { image_url: string } { - if (typeof nodeValue !== "object" || !nodeValue) { - return false; - } - - return "image_url" in nodeValue; - } - - render() { - if (!this.event || this.event.type !== "node") { - return html`No event details available`; - } - - const { node, inputs, outputs } = this.event; - const details = node - .ports(inputs, outputs as OutputValues) - .then((allPorts) => { - const type = node.descriptor.type; - const isOutput = type === "output"; - const portList: { ports: InspectablePort[] } = isOutput - ? allPorts.inputs - : allPorts.outputs; - const ports = portList.ports.filter((port) => { - if (port.star) return false; - if (port.name === "$error") return false; - if (isOutput && port.name === "schema") return false; - - return true; - }); - - return html`
    - ${ports.length > 1 - ? ports.map((port, _idx, arr) => { - const nodeValue = port.value; - let value: HTMLTemplateResult | symbol = nothing; - if (typeof nodeValue === "object") { - if (isLLMContentArray(nodeValue)) { - value = html``; - } else if (isLLMContent(nodeValue)) { - if (!nodeValue.parts) { - // Special case for "$metadata" item. - // See https://github.com/breadboard-ai/breadboard/issues/1673 - // TODO: Make this not ugly. - const data = (nodeValue as unknown as { data: unknown }) - .data; - value = html``; - } else { - if (!nodeValue.parts.length) { - value = html`No data provided`; - } else { - value = html``; - } - } - } else if (this.#isImageURL(nodeValue)) { - value = html``; - } else { - value = html``; - } - } else { - let renderableValue: HTMLTemplateResult | symbol = nothing; - if ( - port.schema.format === "markdown" && - typeof nodeValue === "string" - ) { - renderableValue = html`${markdown(nodeValue)}`; - } else { - renderableValue = html`${nodeValue !== undefined - ? nodeValue - : "No value provided"}`; - } - - // prettier-ignore - value = html`
    ${renderableValue}
    `; - } - - return html`
    - ${arr.length > 1 ? html`

    ${port.title}

    ` : nothing} -
    ${value}
    -
    `; - }) - : html``} -
    `; - }); - - return html`${until(details, html`Loading data...`)}`; - } -} diff --git a/packages/shared-ui/src/elements/google-drive/google-apis.ts b/packages/shared-ui/src/elements/google-drive/google-apis.ts deleted file mode 100644 index bd8d0b23e24..00000000000 --- a/packages/shared-ui/src/elements/google-drive/google-apis.ts +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/// -/// -/// - -let gapiPromise: Promise; -/** - * Load the top-level GAPI (Google API) library. - * - * See https://github.com/google/google-api-javascript-client/blob/master/docs/reference.md - */ -export async function loadGapi(): Promise { - return (gapiPromise ??= (async () => { - await loadNonModuleWithHeadScriptTag("https://apis.google.com/js/api.js"); - return globalThis.gapi; - })()); -} - -let gapiClientPromise: Promise; -/** - * Load the GAPI (Google API) Client library. - * - * See https://github.com/google/google-api-javascript-client/blob/master/docs/reference.md - */ -export async function loadGapiClient(): Promise { - return (gapiClientPromise ??= (async () => { - const gapi = await loadGapi(); - await new Promise((resolve) => gapi.load("client", () => resolve())); - return globalThis.gapi.client; - })()); -} - -let driveApiPromise: Promise; -/** - * Load the the GAPI (Google API) Drive API. - * - * See https://developers.google.com/drive/api/reference/rest/v3 - */ -export async function loadDriveApi(): Promise< - typeof globalThis.gapi.client.drive -> { - return (driveApiPromise ??= (async () => { - const gapiClient = await loadGapiClient(); - await gapiClient.load( - "https://www.googleapis.com/discovery/v1/apis/drive/v3/rest" - ); - return globalThis.gapi.client.drive; - })()); -} - -let drivePickerPromise: Promise; -/** - * Load the the GAPI (Google API) Drive Picker API. - * - * See https://developers.google.com/drive/picker/reference - */ -export async function loadDrivePicker(): Promise< - typeof globalThis.google.picker -> { - return (drivePickerPromise ??= (async () => { - await Promise.all([ - loadDriveApi(), - (async () => { - const gapi = await loadGapi(); - await new Promise((resolve) => gapi.load("picker", resolve)); - })(), - ]); - return globalThis.google.picker; - })()); -} - -/** - * This is like `import`, except for JavaScript that can't be executed as a - * module, like GAPI. - * - * This function does NOT implement caching. - */ -async function loadNonModuleWithHeadScriptTag(src: string): Promise { - const script = document.createElement("script"); - script.async = true; - script.src = src; - - let resolve: () => void; - let reject: () => void; - const promise = new Promise((innerResolve, innerReject) => { - resolve = innerResolve; - reject = innerReject; - }); - - const cancel = new AbortController(); - script.addEventListener( - "load", - () => { - resolve(); - cancel.abort(); - }, - { once: true, signal: cancel.signal } - ); - script.addEventListener( - "error", - () => { - reject(); - cancel.abort(); - }, - { once: true, signal: cancel.signal } - ); - - document.head.appendChild(script); - return promise; -} diff --git a/packages/shared-ui/src/elements/google-drive/google-drive-file-id.ts b/packages/shared-ui/src/elements/google-drive/google-drive-file-id.ts deleted file mode 100644 index 44f78039e9b..00000000000 --- a/packages/shared-ui/src/elements/google-drive/google-drive-file-id.ts +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { LitElement, css, html } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import { type InputEnterEvent } from "../../events/events.js"; -import { InputChangeEvent, InputPlugin } from "../../plugins/input-plugin.js"; -import "../connection/connection-input.js"; -import { loadDrivePicker } from "./google-apis.js"; - -export const googleDriveFileIdInputPlugin: InputPlugin = { - instantiate: { - customElementName: "bb-google-drive-file-id", - }, - match: { - schema: { - type: "string", - behavior: ["google-drive-file-id"], - }, - }, -}; - -@customElement("bb-google-drive-file-id") -export class GoogleDriveFileId extends LitElement { - static styles = css` - :host { - display: flex; - max-width: 400px; - } - - button { - background: var(--bb-inputs-500); - border-radius: 20px; - border: none; - color: white; - cursor: pointer; - font-size: var(--bb-label-large); - padding: 4px 18px; - white-space: nowrap; - } - button:hover { - background-color: var(--bb-inputs-400); - } - - input { - flex-grow: 1; - font-size: 11px; - margin-left: 14px; - padding: 6px 8px; - } - `; - - @state() - private _authorization?: { clientId: string; secret: string }; - - @state() - private _pickerLib?: typeof google.picker; - - @property() - value = ""; - - #picker?: google.picker.Picker; - - override async connectedCallback(): Promise { - super.connectedCallback(); - this._pickerLib ??= await loadDrivePicker(); - } - - override render() { - if (this._authorization === undefined) { - return html``; - } - if (this._pickerLib === undefined) { - return html`

    Loading Google Drive Picker ...

    `; - } - return html` - - - `; - } - - #onToken(event: InputEnterEvent) { - // Prevent ui-controller from receiving an unexpected bbinputenter event. - // - // TODO(aomarks) Let's not re-use bbinputenter here, we should instead use - // bbtokengranted, but there is a small bit of refactoring necessary for - // that to work. - event.stopImmediatePropagation(); - const { clientId, secret } = event.data as { - clientId?: string; - secret?: string; - }; - if (clientId && secret) { - this._authorization = { clientId, secret }; - } - } - - #onClickPickFiles() { - if (this._authorization === undefined || this._pickerLib === undefined) { - return; - } - this.#destroyPicker(); - // See https://developers.google.com/drive/picker/reference - this.#picker = new this._pickerLib.PickerBuilder() - .setAppId(this._authorization.clientId) - .setOAuthToken(this._authorization.secret) - .setCallback(this.#pickerCallback.bind(this)) - .addView(google.picker.ViewId.DOCS) - .enableFeature(google.picker.Feature.NAV_HIDDEN) - .build(); - this.#picker.setVisible(true); - } - - #pickerCallback(result: google.picker.ResponseObject): void { - switch (result.action) { - case "cancel": { - this.#destroyPicker(); - return; - } - case "picked": { - this.#destroyPicker(); - // TODO(aomarks) Show this as a snackbar - console.log(`Shared 1 Google Drive file with Breadboard`); - if (result.docs.length > 0) { - this.value = result.docs[0].id; - this.dispatchEvent(new InputChangeEvent(this.value)); - } - } - } - } - - #destroyPicker() { - if (this.#picker === undefined) { - return; - } - this.#picker.setVisible(false); - this.#picker.dispose(); - this.#picker = undefined; - } - - #onQueryInput(event: { target: HTMLTextAreaElement }) { - this.value = event.target.value; - this.dispatchEvent(new InputChangeEvent(this.value)); - } -} diff --git a/packages/shared-ui/src/elements/google-drive/google-drive-query.ts b/packages/shared-ui/src/elements/google-drive/google-drive-query.ts deleted file mode 100644 index 606c3d7b2f6..00000000000 --- a/packages/shared-ui/src/elements/google-drive/google-drive-query.ts +++ /dev/null @@ -1,192 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { LitElement, css, html } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import type { InputPlugin } from "../../plugins/input-plugin.js"; -import { type InputEnterEvent } from "../../events/events.js"; -import "../connection/connection-input.js"; -import { loadDrivePicker } from "./google-apis.js"; - -export const googleDriveQueryInputPlugin: InputPlugin = { - instantiate: { - customElementName: "bb-google-drive-query", - }, - match: { - schema: { - type: "string", - behavior: ["google-drive-query"], - }, - }, -}; - -@customElement("bb-google-drive-query") -export class GoogleDriveQuery extends LitElement { - static styles = css` - :host { - display: flex; - flex-direction: column; - max-width: 400px; - } - - #query { - display: flex; - flex-direction: column; - } - #query > textarea { - box-sizing: border-box; - height: 4lh; - margin-top: 14px; - padding: 8px; - width: 100%; - } - #query > a { - align-self: flex-end; - color: var(--bb-ui-600); - font-size: 11px; - margin-top: 4px; - } - - #sharing { - display: flex; - margin-top: 14px; - } - #sharing > button { - background: var(--bb-inputs-500); - border-radius: 20px; - border: none; - color: white; - cursor: pointer; - font-size: var(--bb-label-large); - max-height: 32px; - padding: 4px 18px; - white-space: nowrap; - } - #sharing > button:hover { - background-color: var(--bb-inputs-400); - } - #sharing > p { - color: var(--bb-neutral-600); - font-size: 11px; - margin: 0 0 0 12px; - text-align: justify; - } - `; - - @state() - private _authorization?: { clientId: string; secret: string }; - - @state() - private _pickerLib?: typeof google.picker; - - @property() - value = ""; - - #picker?: google.picker.Picker; - - override async connectedCallback(): Promise { - super.connectedCallback(); - this._pickerLib ??= await loadDrivePicker(); - } - - override render() { - if (this._authorization === undefined) { - return html``; - } - if (this._pickerLib === undefined) { - return html`

    Loading Google Drive Picker ...

    `; - } - return html` -
    - - Syntax Documentation -
    - -
    - -

    - The query above only matches files you have shared with Breadboard - (including all previously shared files). Click to share additional - files. Hold Shift for multi-select. -

    -
    - `; - } - - #onToken(event: InputEnterEvent) { - // Prevent ui-controller from receiving an unexpected bbinputenter event. - // - // TODO(aomarks) Let's not re-use bbinputenter here, we should instead use - // bbtokengranted, but there is a small bit of refactoring necessary for - // that to work. - event.stopImmediatePropagation(); - const { clientId, secret } = event.data as { - clientId?: string; - secret?: string; - }; - if (clientId && secret) { - this._authorization = { clientId, secret }; - } - } - - #onClickPickFiles() { - if (this._authorization === undefined || this._pickerLib === undefined) { - return; - } - this.#destroyPicker(); - // See https://developers.google.com/drive/picker/reference - this.#picker = new this._pickerLib.PickerBuilder() - .setAppId(this._authorization.clientId) - .setOAuthToken(this._authorization.secret) - .setCallback(this.#pickerCallback.bind(this)) - .addView(google.picker.ViewId.DOCS) - .enableFeature(google.picker.Feature.NAV_HIDDEN) - .enableFeature(google.picker.Feature.MULTISELECT_ENABLED) - .build(); - this.#picker.setVisible(true); - } - - #pickerCallback(result: google.picker.ResponseObject): void { - switch (result.action) { - case "cancel": { - this.#destroyPicker(); - return; - } - case "picked": { - this.#destroyPicker(); - // TODO(aomarks) Show this as a snackbar - console.log( - `Shared ${result.docs.length} Google Drive files with Breadboard` - ); - } - } - } - - #destroyPicker() { - if (this.#picker === undefined) { - return; - } - this.#picker.setVisible(false); - this.#picker.dispose(); - this.#picker = undefined; - } - - #onQueryInput(event: { target: HTMLTextAreaElement }) { - this.value = event.target.value; - } -} diff --git a/packages/shared-ui/src/elements/graph-history/graph-history.ts b/packages/shared-ui/src/elements/graph-history/graph-history.ts deleted file mode 100644 index fd41f9029fe..00000000000 --- a/packages/shared-ui/src/elements/graph-history/graph-history.ts +++ /dev/null @@ -1,162 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { EditHistoryEntry } from "@google-labs/breadboard"; -import { LitElement, html, css, nothing } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { classMap } from "lit/directives/class-map.js"; -import { map } from "lit/directives/map.js"; -import { RedoEvent, UndoEvent } from "../../events/events.js"; - -@customElement("bb-graph-history") -export class GraphHistory extends LitElement { - @property() - entries: EditHistoryEntry[] | null = null; - - @property() - count: number = -1; - - @property() - canRedo = false; - - @property() - canUndo = false; - - @property() - idx = -1; - - static styles = css` - :host { - display: grid; - grid-template-rows: 36px auto; - position: fixed; - top: 120px; - left: 10px; - border-radius: var(--bb-grid-size-2); - color: var(--bb-neutral-0); - padding: var(--bb-grid-size-3); - height: 100%; - max-height: 30vh; - overflow: auto; - width: 100%; - max-width: 35vh; - z-index: 1000; - } - - #underlay { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: var(--bb-ui-900); - opacity: 0.92; - } - - h1 { - display: flex; - align-items: center; - font: 400 var(--bb-title-medium) / var(--bb-title-line-height-medium) - var(--bb-font-family); - margin: 0; - padding: 0 0 var(--bb-grid-size-3) 0; - z-index: 1; - position: relative; - } - - h1 span { - flex: 1; - } - - #undo, - #redo { - width: 20px; - height: 20px; - margin-left: var(--bb-grid-size-2); - border: none; - font-size: 0; - cursor: pointer; - } - - #undo { - background: transparent var(--bb-icon-undo-inverted) center center / 20px - 20px no-repeat; - } - - #redo { - background: transparent var(--bb-icon-redo-inverted) center center / 20px - 20px no-repeat; - } - - #undo[disabled], - #redo[disabled] { - opacity: 0.4; - cursor: auto; - } - - ol { - position: relative; - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - margin: 0; - padding: 0 var(--bb-grid-size-3) 0 var(--bb-grid-size-7); - overflow-y: scroll; - scrollbar-gutter: stable; - } - - li { - margin-bottom: var(--bb-grid-size); - } - - li.current { - color: var(--bb-nodes-300); - } - `; - - render() { - if (!this.entries) { - return nothing; - } - - return html`
    -

    - Change History - -

    -
      - ${map(this.entries, (entry, idx) => { - return html`
    1. - ${entry.label} -
    2. `; - })} -
    `; - } -} diff --git a/packages/shared-ui/src/elements/input/array/array-editor.ts b/packages/shared-ui/src/elements/input/array/array-editor.ts deleted file mode 100644 index d6c2ce0aa4d..00000000000 --- a/packages/shared-ui/src/elements/input/array/array-editor.ts +++ /dev/null @@ -1,496 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - BehaviorSchema, - GraphDescriptor, - GraphProvider, -} from "@google-labs/breadboard"; -import { LitElement, html, css, HTMLTemplateResult, nothing } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { map } from "lit/directives/map.js"; -import { Ref, createRef, ref } from "lit/directives/ref.js"; -import { LLMInput } from "../llm-input/llm-input"; - -enum TYPE { - STRING = "string", - OBJECT = "object", - NUMBER = "number", - BOOLEAN = "boolean", -} - -type ArrayEditorType = string | number | object | boolean | null; - -@customElement("bb-array-editor") -export class ArrayEditor extends LitElement { - @property({ reflect: true }) - type = TYPE.STRING; - - @property() - items: ArrayEditorType[] | null = null; - - @property({ reflect: true }) - behavior: BehaviorSchema | null = null; - - @property() - providers: GraphProvider[] = []; - - @property() - providerOps = 0; - - @property() - graph: GraphDescriptor | null = null; - - #formRef: Ref = createRef(); - #appendNewItemOnNextRender = false; - - static styles = css` - :host { - display: block; - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - } - - ul { - list-style: none; - padding: 0; - margin: 0; - display: grid; - row-gap: var(--bb-grid-size); - } - - li { - overflow: auto; - display: flex; - align-items: center; - } - - input[type="number"], - input[type="text"], - select, - textarea { - resize: none; - display: block; - box-sizing: border-box; - width: 100%; - field-sizing: content; - font-family: var(--bb-font-family-mono); - font-size: var(--bb-body-x-small); - line-height: var(--bb-body-line-height-x-small); - max-height: 300px; - flex: 1; - } - - input[type="checkbox"] { - margin: 0; - } - - .delete { - width: 16px; - height: 16px; - background: none; - background-image: var(--bb-icon-delete); - background-position: center center; - background-repeat: no-repeat; - background-size: 16px 16px; - border: none; - font-size: 0; - opacity: 0.5; - cursor: pointer; - margin-left: var(--bb-grid-size); - } - - .delete:hover { - opacity: 1; - } - - .no-items { - color: var(--bb-neutral-500); - line-height: calc(var(--bb-grid-size) * 5); - } - - #add-new-item { - width: 16px; - height: 16px; - background: var(--bb-icon-add-circle) center center no-repeat; - background-size: 16px 16px; - border: none; - font-size: 0; - opacity: 0.5; - cursor: pointer; - } - - #add-new-item:hover { - opacity: 1; - } - - #unset-all-items, - #create { - font-size: var(--bb-label-small); - background: var(--bb-continue-color); - color: #246db5; - border-radius: 20px; - border: none; - height: calc(var(--bb-grid-size) * 4); - padding: 0 calc(var(--bb-grid-size) * 2); - margin: 0 0 0 var(--bb-grid-size); - } - `; - - get value() { - return JSON.stringify(this.items); - } - - #addItem() { - if (!this.items) { - this.items = []; - } - - this.#appendNewItemOnNextRender = true; - if (!this.#updateItems()) { - return; - } - - this.requestUpdate(); - } - - #removeItem(evt: Event) { - if ( - !(evt.target instanceof HTMLButtonElement) || - !this.items || - !this.#formRef.value - ) { - return; - } - - if (!confirm("Are you sure you want to remove this item?")) { - return; - } - - const idxAsStr = evt.target.dataset.idx; - if (!idxAsStr) { - return; - } - - const idx = parseInt(idxAsStr, 10); - if (Number.isNaN(idx)) { - return; - } - - this.items.splice(idx, 1); - this.#notify(); - this.requestUpdate(); - } - - #unsetAll() { - if (!confirm("Are you sure you want to unset all items in this array?")) { - return; - } - - this.items = null; - this.#notify(); - this.requestUpdate(); - } - - #updateItems() { - if (!this.#formRef.value) { - return true; - } - - const form = this.#formRef.value; - const items: ArrayEditorType[] = []; - - for (const entry of form.querySelectorAll(".entry")) { - if ("setCustomValidity" in entry) { - entry.setCustomValidity(""); - } - - switch (this.type) { - case TYPE.STRING: { - items.push(entry.value); - break; - } - - case TYPE.NUMBER: { - items.push( - Number.isNaN(entry.valueAsNumber) ? null : entry.valueAsNumber - ); - break; - } - - case TYPE.BOOLEAN: { - items.push(entry.checked); - break; - } - - case TYPE.OBJECT: { - if (this.behavior === "llm-content") { - (entry as unknown as LLMInput).processAllOpenParts(); - items.push(entry.value); - break; - } - - if (this.behavior === "board") { - items.push(entry.value); - break; - } - - try { - items.push(JSON.parse(entry.value)); - } catch (err) { - console.warn("Unable to parse", entry.value); - console.warn(err); - } - break; - } - } - } - - this.items = items; - } - - #notify() { - // Report up to the container that there's been successful input. - this.dispatchEvent( - new InputEvent("input", { bubbles: true, composed: true }) - ); - } - - protected willUpdate(): void { - if (!this.#appendNewItemOnNextRender || !this.items) { - return; - } - - const items = [...this.items]; - switch (this.type) { - case TYPE.STRING: - case TYPE.NUMBER: { - items.push(""); - break; - } - - case TYPE.BOOLEAN: { - items.push(false); - break; - } - - case TYPE.OBJECT: { - if (this.behavior === "board") { - items.push(null); - break; - } else if (this.behavior === "llm-content") { - items.push({ - role: "user", - parts: [], - }); - break; - } - - items.push({}); - break; - } - } - - this.items = items; - } - - protected updated(): void { - if (!this.#appendNewItemOnNextRender || !this.#formRef.value) { - return; - } - - this.#appendNewItemOnNextRender = false; - - const inputs = this.#formRef.value.querySelectorAll("textarea"); - if (inputs.length === 0) { - return; - } - inputs[inputs.length - 1].focus(); - } - - render() { - if (!this.items) { - return html`(Not set) - `; - } - - return html`
    { - evt.preventDefault(); - evt.stopImmediatePropagation(); - - if ( - evt.target instanceof HTMLInputElement || - evt.target instanceof HTMLTextAreaElement - ) { - evt.target.setCustomValidity(""); - } - - this.#updateItems(); - this.#notify(); - }} - @blur=${(evt: InputEvent) => { - evt.preventDefault(); - evt.stopImmediatePropagation(); - this.#updateItems(); - this.#notify(); - }} - @submit=${(evt: Event) => evt.preventDefault()} - > -
      - ${this.items.length - ? map(this.items, (item, idx) => { - let selector: HTMLTemplateResult | symbol = nothing; - switch (this.type) { - case TYPE.STRING: { - selector = html``; - break; - } - - case TYPE.NUMBER: { - selector = html``; - break; - } - - case TYPE.BOOLEAN: { - selector = html``; - break; - } - - case TYPE.OBJECT: { - if (this.behavior === "board") { - selector = html``; - break; - } else if (this.behavior === "llm-content") { - // const value = JSON.stringify(item, null, 2); - selector = html``; - break; - } - - selector = html``; - break; - } - - default: { - console.warn(`Unexpected type for array: ${this.type}`); - return nothing; - } - } - - return html`
    • - ${selector} - -
    • `; - }) - : html`
    • (No items)
    • `} -
    • - - -
    • -
    -
    `; - } -} diff --git a/packages/shared-ui/src/elements/input/audio/audio.ts b/packages/shared-ui/src/elements/input/audio/audio.ts deleted file mode 100644 index 43d84a20e6b..00000000000 --- a/packages/shared-ui/src/elements/input/audio/audio.ts +++ /dev/null @@ -1,210 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { LitElement, html, css, nothing } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import { Task } from "@lit/task"; -import { Ref, createRef, ref } from "lit/directives/ref.js"; -import { asBase64, LLMContent } from "@google-labs/breadboard"; - -@customElement("bb-audio-input") -export class AudioInput extends LitElement { - @property() - audio: string | null = null; - - @state() - recording: boolean = false; - - #stream: MediaStream | null = null; - #output: string | null = null; - #mimeType: string = "audio/ogg"; - #audioRef: Ref = createRef(); - #recorder: MediaRecorder | null = null; - #parts: Blob[] = []; - - #permissionTask = new Task(this, { - task: async () => { - const devices = await navigator.mediaDevices.enumerateDevices(); - if ( - !devices || - devices.every((d) => d.label === null || d.label === "") - ) { - throw new Error("No permission"); - } - }, - args: () => [], - }); - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: block; - } - - #play-audio { - background: #fff var(--bb-icon-sound) 6px 3px / 16px 16px no-repeat; - border-radius: 20px; - color: var(--bb-neutral-900); - border: 1px solid var(--bb-neutral-600); - height: 24px; - padding: 0 16px 0 28px; - margin: calc(var(--bb-grid-size) * 2) 0 var(--bb-grid-size) 0; - cursor: pointer; - opacity: 0.5; - } - - #play-audio:hover, - #play-audio:focus { - opacity: 1; - } - - #capture { - background: var(--bb-inputs-100); - background-image: var(--bb-icon-mic-green); - background-size: 16px 16px; - background-position: 8px 4px; - background-repeat: no-repeat; - color: var(--bb-inputs-800); - border-radius: 20px; - border: none; - height: 24px; - padding: 0 16px 0 28px; - margin: calc(var(--bb-grid-size) * 2) 0 var(--bb-grid-size) 0; - cursor: pointer; - } - - #capture:hover, - #capture:focus { - opacity: 1; - } - `; - - get value(): LLMContent { - return { - role: "user", - parts: [ - { - inlineData: { data: this.#output || "", mimeType: this.#mimeType }, - }, - ], - }; - } - - async #requestPermission() { - const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); - for (const track of stream.getAudioTracks()) { - track.stop(); - } - - this.#permissionTask.run(); - } - - async #startRecording() { - this.#output = null; - this.#parts = []; - if (this.audio) { - URL.revokeObjectURL(this.audio); - this.audio = null; - } - - this.#stream = await navigator.mediaDevices.getUserMedia({ audio: true }); - const audioTracks = this.#stream.getAudioTracks(); - if (audioTracks.length === 0) { - this.#stopRecording(); - return; - } - - this.#recorder = new MediaRecorder(this.#stream, { - mimeType: "audio/webm", - }); - - this.#recorder.addEventListener("dataavailable", (evt) => { - this.#mimeType = evt.data.type.replace(/;.*$/, ""); - this.#parts.push(evt.data); - }); - - this.#recorder.addEventListener("stop", async () => { - // Take all the audio parts received and combine them into one Blob. - const audioFile = new Blob(this.#parts, { - type: this.#mimeType, - }); - // Create a preview for the user. - this.audio = URL.createObjectURL(audioFile); - this.#output = await asBase64(audioFile); - }); - - this.#recorder.start(); - } - - #stopRecording() { - if (this.#recorder) { - this.#recorder.stop(); - } - - const stream = this.#stream; - if (!stream) { - return; - } - - for (const track of stream.getAudioTracks()) { - track.stop(); - } - } - - render() { - return this.#permissionTask.render({ - pending: () => html`Checking permission...`, - complete: () => { - return html` - ${this.recording ? "Recording..." : nothing} - ${this.audio - ? html`` - : nothing}`; - }, - error: () => - html``, - }); - } -} diff --git a/packages/shared-ui/src/elements/input/board-selector/board-selector.ts b/packages/shared-ui/src/elements/input/board-selector/board-selector.ts deleted file mode 100644 index 972285a7d46..00000000000 --- a/packages/shared-ui/src/elements/input/board-selector/board-selector.ts +++ /dev/null @@ -1,267 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { - GraphDescriptor, - GraphProvider, - SubGraphs, -} from "@google-labs/breadboard"; -import { LitElement, html, css, nothing } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import { map } from "lit/directives/map.js"; -import { Ref, createRef, ref } from "lit/directives/ref.js"; -import { SubGraphChosenEvent } from "../../../events/events.js"; - -@customElement("bb-board-selector") -export class BoardSelector extends LitElement { - @property() - graph: GraphDescriptor | null = null; - - @property() - providers: GraphProvider[] = []; - - @property() - providerOps = 0; - - @property() - subGraphs: SubGraphs | null = null; - - @state() - usingCustomURL = false; - - #inputRef: Ref = createRef(); - #selectorRef: Ref = createRef(); - #board: string | null = null; - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: block; - } - - #board-selector { - display: grid; - grid-template-columns: 1fr auto; - } - - #quick-switch { - height: 32px; - width: 24px; - margin-left: 12px; - opacity: 0.5; - border: none; - background: var(--bb-icon-quick-jump) center center no-repeat; - font-size: 0; - cursor: pointer; - } - - #quick-switch:hover { - opacity: 1; - } - - select { - display: block; - font-family: var(--bb-font-family-mono); - font-size: var(--bb-body-x-small); - line-height: var(--bb-body-line-height-x-small); - border-radius: var(--bb-grid-size); - background: rgb(255, 255, 255); - padding: var(--bb-input-padding, calc(var(--bb-grid-size) * 2)); - border: 1px solid rgb(209, 209, 209); - width: 100%; - } - - input { - font-family: var(--bb-font-family-mono); - font-size: var(--bb-body-x-small); - line-height: var(--bb-body-line-height-x-small); - resize: none; - display: block; - box-sizing: border-box; - width: 100%; - field-sizing: content; - max-height: 300px; - border-radius: var(--bb-grid-size); - background: rgb(255, 255, 255); - padding: var(--bb-input-padding, calc(var(--bb-grid-size) * 2)); - border: 1px solid rgb(209, 209, 209); - margin-top: var(--bb-grid-size); - } - `; - - get value() { - if (this.#inputRef.value) { - if (!this.#inputRef.value.checkValidity()) { - this.#inputRef.value.reportValidity(); - } - - return this.#inputRef.value.value; - } - - if (!this.#selectorRef.value) { - return null; - } - - return this.#selectorRef.value.value; - } - - set value(value: string | null) { - this.#board = value; - this.requestUpdate(); - } - - protected willUpdate(): void { - if (this.subGraphs && this.#board && this.subGraphs[this.#board.slice(1)]) { - this.usingCustomURL = false; - return; - } - - for (const provider of this.providers) { - for (const [, store] of provider.items()) { - for (const [, { url, tags }] of store.items) { - const expandedUrl = new URL(url, window.location.href); - if (this.#board === expandedUrl.href && tags?.includes("tool")) { - this.usingCustomURL = false; - return; - } - } - } - } - - if (this.#board === "") { - return; - } - - this.usingCustomURL = true; - } - - render() { - const showQuickSwitch = this.#board && this.#board.startsWith("#"); - const providers = this.providers.filter((provider) => - this.graph && this.graph.url - ? provider.canProvide(new URL(this.graph.url)) - : false - ); - - return html`
    -
    - - ${showQuickSwitch - ? html`` - : nothing} -
    - ${this.usingCustomURL - ? html` { - if (!(evt.target instanceof HTMLInputElement)) { - return; - } - - if (!evt.target.checkValidity()) { - evt.stopImmediatePropagation(); - } - }} - @blur=${(evt: Event) => { - if (!(evt.target instanceof HTMLInputElement)) { - return; - } - - if (!evt.target.checkValidity()) { - evt.target.reportValidity(); - evt.stopImmediatePropagation(); - } - }} - type="url" - .value=${this.#board} - />` - : nothing} -
    `; - } -} diff --git a/packages/shared-ui/src/elements/input/code-editor/code-editor.ts b/packages/shared-ui/src/elements/input/code-editor/code-editor.ts deleted file mode 100644 index 472b4a0b92f..00000000000 --- a/packages/shared-ui/src/elements/input/code-editor/code-editor.ts +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { LitElement, html, css } from "lit"; -import { customElement } from "lit/decorators.js"; -import { Ref, createRef, ref } from "lit/directives/ref.js"; -import { EditorView, minimalSetup } from "codemirror"; -import { keymap } from "@codemirror/view"; -import { javascript } from "@codemirror/lang-javascript"; -import { closeBrackets } from "@codemirror/autocomplete"; -import { indentWithTab } from "@codemirror/commands"; -import { CodeChangeEvent } from "../../../events/events.js"; - -@customElement("bb-code-editor") -export class CodeEditor extends LitElement { - #editor: EditorView | null = null; - #content: Ref = createRef(); - #value: string | null = null; - - #onKeyUpBound = this.#onKeyUp.bind(this); - - static styles = css` - :host { - display: block; - font-size: 11px; - } - - .cm-editor { - border-radius: var(--bb-grid-size); - background: rgb(255, 255, 255); - padding: var(--bb-input-padding, calc(var(--bb-grid-size) * 2)); - border: 1px solid rgb(209, 209, 209); - } - - .cm-editor.cm-focused { - outline: none; - border: 1px solid var(--bb-ui-700); - box-shadow: inset 0 0 0 1px var(--bb-ui-700); - } - - textarea { - background: rgb(255, 255, 255); - border-radius: var(--bb-grid-size); - border: 1px solid rgb(209, 209, 209); - box-sizing: border-box; - display: block; - field-sizing: content; - font-family: var(--bb-font-family-mono); - font-size: var(--bb-body-small); - line-height: var(--bb-body-line-height-small); - max-height: 300px; - padding: var(--bb-input-padding, calc(var(--bb-grid-size) * 2)); - resize: none; - width: 100%; - } - `; - - set value(value: string | null) { - this.#value = value; - this.#attemptEditorUpdate(); - } - - get value() { - if (!this.#editor) { - return null; - } - - this.#value = this.#editor.state.doc.toString(); - return this.#value; - } - - #attemptEditorUpdate() { - if (!this.#editor) { - return; - } - - const state = this.#editor.state; - const transaction = state.update({ - changes: { from: 0, to: state.doc.length, insert: this.#value || "" }, - }); - - this.#editor.dispatch(transaction); - } - - protected firstUpdated(): void { - this.#editor = new EditorView({ - extensions: [ - minimalSetup, - javascript(), - closeBrackets(), - keymap.of([indentWithTab]), - ], - parent: this.#content.value, - }); - - this.#attemptEditorUpdate(); - } - - #onKeyUp() { - this.dispatchEvent(new CodeChangeEvent()); - } - - connectedCallback(): void { - super.connectedCallback(); - - this.addEventListener("keyup", this.#onKeyUpBound); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - - this.removeEventListener("keyup", this.#onKeyUpBound); - } - - render() { - return html`
    `; - } - - destroy() { - if (!this.#editor) { - return; - } - - this.#editor.destroy(); - this.#editor = null; - } -} diff --git a/packages/shared-ui/src/elements/input/delegating-input.ts b/packages/shared-ui/src/elements/input/delegating-input.ts deleted file mode 100644 index 03b66aff2f5..00000000000 --- a/packages/shared-ui/src/elements/input/delegating-input.ts +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { analyzeIsJsonSubSchema } from "@google-labs/breadboard-schema/subschema.js"; -import { consume } from "@lit/context"; -import { Task } from "@lit/task"; -import type { JSONSchema4 } from "json-schema"; -import { html, LitElement } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { - type Environment, - environmentContext, -} from "../../contexts/environment.js"; -import type { - InputChangeEvent, - InputPlugin, - InputWidget, -} from "../../plugins/input-plugin.js"; - -/** - * An input widget which doesn't render anything directly, but instead matches - * the current schema against the input widgets that are installed in our - * environment, and instantiates one of those. - */ -@customElement("bb-delegating-input") -export class DelegatingInput - extends LitElement - implements InputWidget -{ - @property({ attribute: false }) - schema?: JSONSchema4; - - // See #onChange for why we maintain a private #value shadow. - #value: unknown; - @property({ attribute: false }) - get value(): unknown { - return this.#value; - } - set value(value: unknown) { - this.#value = value; - } - - @consume({ context: environmentContext }) - private _environment?: Environment; - - /** - * This first task chooses the best plugin and instantiates the inner widget - * element. - */ - #widgetIgnoringValue = new Task(this, { - args: () => [this.schema, this._environment] as const, - task: ([schema, environment], { signal }) => { - if (!schema || !environment) { - return undefined; - } - const plugin = chooseBestPlugin(schema, environment); - if (!plugin) { - throw new Error( - ` could not find an input widget capable of ` + - `handling schema: ${JSON.stringify(schema)}` - ); - } - return this.#instantiateWidget(plugin, schema, signal); - }, - }); - - /** - * This second task propagates any values set from our parent down to the - * inner widget element. - * - * Note this is a separate task from #widgetIgnoringValue so that when it's - * only the value that changed, we don't re-instantiate the element. - */ - #widget = new Task(this, { - args: () => [this.#widgetIgnoringValue.value, this.#value] as const, - task: ([widget, value]) => { - if (widget) { - widget.value = value; - } - return widget; - }, - }); - - override render() { - return this.#widget.render({ - pending: () => html`

    Loading input...

    `, - error: (error) => html`

    Error delegating to input: ${error}

    `, - complete: (widget) => widget, - }); - } - - async #instantiateWidget( - plugin: InputPlugin, - schema: JSONSchema4, - signal: AbortSignal - ): Promise { - await plugin.load?.(signal); - if (signal.aborted) { - return undefined; - } - const element = document.createElement( - plugin.instantiate.customElementName - ) as InputWidget; - element.schema = schema; - element.addEventListener("bb-input-change", this.#onChange, { signal }); - return element; - } - - #onChange = (event: InputChangeEvent) => { - // Set the #value shadow to avoid redundantly setting the value back on the - // widget element via the #widget task, since we can assume it already knows - // about the value it just dispatched an event for. - this.#value = event.value; - this.dispatchEvent(new Event("input")); - }; -} - -declare global { - interface HTMLElementTagNameMap { - "bb-delegating-input": DelegatingInput; - } -} - -function chooseBestPlugin(schema: JSONSchema4, environment: Environment) { - // TODO(aomarks) Performance of this search could be improved by - // partitioning by the top-level "type" field. But note we have to account - // for schema compositions like `{ anyOf: { ... } }`, so it's not so - // simple. - for (const plugin of environment.plugins.input) { - // TODO If there are ties, a good starting heuristic could be to prefer - // the widget with the most narrowly defined schema, and a proxy for - // that could simply be JSON.stringify(match.schema).length. - if (analyzeIsJsonSubSchema(schema, plugin.match.schema).isSubSchema) { - return plugin; - } - } -} diff --git a/packages/shared-ui/src/elements/input/drawable/drawable.ts b/packages/shared-ui/src/elements/input/drawable/drawable.ts deleted file mode 100644 index 0edce1de069..00000000000 --- a/packages/shared-ui/src/elements/input/drawable/drawable.ts +++ /dev/null @@ -1,330 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { LLMContent } from "@google-labs/breadboard"; -import { LitElement, html, css } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import { createRef, ref, type Ref } from "lit/directives/ref.js"; - -@customElement("bb-drawable-input") -export class DrawableInput extends LitElement { - @property() - type = "image/png"; - - @state() - error = ""; - - @state() - strokeColor = "#333333"; - - #drawing = false; - #canvasRef: Ref = createRef(); - #bounds = { x: 0, y: 0 }; - #lastPosition = { x: 0, y: 0 }; - #lastDimensions = { w: 0, h: 0 }; - #onWindowResizeBound = this.#onWindowResize.bind(this); - - static styles = css` - :host { - --default-bb-box-shadow: 0 6px 9px 0 rgba(0, 0, 0, 0.12), - 0 2px 3px 0 rgba(0, 0, 0, 0.23); - --default-bb-border-radius: 8px; - --default-bb-input-background-color: #fff; - --default-bb-outline: transparent; - - position: relative; - display: block; - width: 100%; - background-color: var( - --bb-input-background-color, - var(--default-bb-input-background-color) - ); - box-shadow: var(--bb-box-shadow, var(--default-bb-box-shadow)); - border-radius: var(--bb-border-radius, var(--default-bb-border-radius)); - aspect-ratio: 4/3; - outline: 1px solid var(--bb-outline, var(--default-bb-outline)); - } - - canvas { - display: block; - width: 100%; - height: 100%; - opacity: 0; - border-radius: var(--bb-border-radius, var(--default-bb-border-radius)); - animation: fadeIn 0.3s cubic-bezier(0, 0, 0.3, 1) both; - animation-delay: 0.3s; - } - - canvas.active { - animation: fadeIn 0.3s cubic-bezier(0, 0, 0.3, 1) both; - animation-delay: 0.3s; - } - - #controls { - width: calc(var(--bb-grid-size) * 8); - position: absolute; - top: calc(var(--bb-grid-size) * 4); - left: calc(var(--bb-grid-size) * 4); - padding: calc(var(--bb-grid-size) * 0.5); - background: rgb(255, 255, 255); - border: 1px solid rgb(237, 237, 237); - border-radius: calc(var(--bb-grid-size) * 2); - cursor: auto; - z-index: 1; - } - - #controls > button#reset-image { - background-image: var(--bb-icon-reset-image); - } - - #controls > button:first-child { - margin-top: 0px; - } - - #color-input, - #controls > button { - width: 32px; - height: 32px; - font-size: 0; - border-radius: calc(var(--bb-grid-size) * 1.5); - border: none; - background: none; - display: block; - margin-top: 4px; - cursor: pointer; - } - - #controls > button { - background-color: rgb(255, 255, 255); - background-position: center center; - background-repeat: no-repeat; - opacity: 0.5; - } - - #controls > button:hover, - #controls > button.active { - background-color: rgb(230, 241, 242); - opacity: 1; - } - - @keyframes fadeIn { - from { - opacity: 0; - } - - to { - opacity: 1; - } - } - `; - - connectedCallback(): void { - super.connectedCallback(); - - window.addEventListener("resize", this.#onWindowResizeBound); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - - window.removeEventListener("resize", this.#onWindowResizeBound); - } - - #onColorInput(evt: InputEvent) { - if (!(evt.target instanceof HTMLInputElement)) { - return; - } - - this.strokeColor = evt.target.value; - } - - #fillCanvas() { - if (!this.#canvasRef.value) { - return; - } - - const ctx = this.#canvasRef.value.getContext("2d"); - if (!ctx) { - return; - } - - ctx.fillStyle = "#FFF"; - ctx.fillRect(0, 0, this.#lastDimensions.w, this.#lastDimensions.h); - } - - #onReset() { - this.#fillCanvas(); - } - - #onWindowResize() { - if (!this.#canvasRef.value) { - return; - } - - const canvas = this.#canvasRef.value; - const ctx = canvas.getContext("2d", { willReadFrequently: true }); - if (!ctx) { - return; - } - - let { width, height } = canvas.getBoundingClientRect(); - width = Math.floor(width); - height = Math.floor(height); - - // Preserve the image during the resize. - let imageData: ImageData | null = null; - if (this.#lastDimensions.w !== 0 && this.#lastDimensions.h !== 0) { - imageData = ctx.getImageData( - 0, - 0, - this.#lastDimensions.w, - this.#lastDimensions.h - ); - } - - canvas.width = width; - canvas.height = height; - - this.#lastDimensions.w = width; - this.#lastDimensions.h = height; - - this.#fillCanvas(); - - if (imageData !== null) { - ctx.putImageData(imageData, 0, 0); - } - } - - #onPointerDown(evt: PointerEvent) { - if (!this.#canvasRef.value) { - return; - } - - const canvas = this.#canvasRef.value; - const ctx = canvas.getContext("2d", { willReadFrequently: true }); - if (!ctx) { - return; - } - - if (evt.composedPath()[0] !== canvas) { - return; - } - - const bounds = canvas.getBoundingClientRect(); - const { x, y } = bounds; - const width = Math.floor(bounds.width); - const height = Math.floor(bounds.height); - - if (this.#lastDimensions.w !== width || this.#lastDimensions.h !== height) { - this.#onWindowResize(); - } - - canvas.setPointerCapture(evt.pointerId); - - this.#drawing = true; - this.#bounds.x = x; - this.#bounds.y = y; - - ctx.strokeStyle = this.strokeColor; - ctx.lineCap = "round"; - ctx.lineWidth = 3; - - const startX = evt.pageX - this.#bounds.x + window.scrollX; - const startY = evt.pageY - this.#bounds.y - window.scrollY; - - ctx.beginPath(); - ctx.moveTo(startX, startY); - - this.#lastPosition.x = startX; - this.#lastPosition.y = startY; - } - - #onPointerUp() { - if (!this.#drawing) { - return; - } - - this.#drawing = false; - - if (!this.#canvasRef.value) { - return; - } - - const canvas = this.#canvasRef.value; - const ctx = canvas.getContext("2d", { willReadFrequently: true }); - if (!ctx) { - return; - } - - ctx.closePath(); - } - - #onPointerMove(evt: PointerEvent) { - if (!this.#drawing) { - return; - } - - if (!this.#canvasRef.value) { - return; - } - - const canvas = this.#canvasRef.value; - const ctx = canvas.getContext("2d", { willReadFrequently: true }); - if (!ctx) { - return; - } - - ctx.moveTo(this.#lastPosition.x, this.#lastPosition.y); - - const x = evt.pageX - this.#bounds.x + window.scrollX; - const y = evt.pageY - this.#bounds.y - window.scrollY; - - ctx.lineTo(x, y); - ctx.stroke(); - - this.#lastPosition.x = x; - this.#lastPosition.y = y; - } - - get value(): LLMContent { - const inlineData = this.#canvasRef.value?.toDataURL(this.type, 80) || ""; - const preamble = `data:${this.type};base64,`; - - return { - role: "user", - parts: [ - { - inlineData: { - data: inlineData.substring(preamble.length), - mimeType: this.type, - }, - }, - ], - }; - } - - render() { - if (this.error) { - return html`${this.error}`; - } - - return html`
    - - -
    - `; - } -} diff --git a/packages/shared-ui/src/elements/input/llm-input/llm-input-array.ts b/packages/shared-ui/src/elements/input/llm-input/llm-input-array.ts deleted file mode 100644 index d57d570d6bb..00000000000 --- a/packages/shared-ui/src/elements/input/llm-input/llm-input-array.ts +++ /dev/null @@ -1,258 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { LitElement, html, css, nothing, PropertyValueMap } from "lit"; -import { customElement, property } from "lit/decorators.js"; -import { AllowedLLMContentTypes } from "../../../types/types.js"; -import { map } from "lit/directives/map.js"; -import { Ref, createRef, ref } from "lit/directives/ref.js"; -import { LLMInput } from "./llm-input.js"; -import { classMap } from "lit/directives/class-map.js"; -import { LLMContent } from "@google-labs/breadboard"; - -@customElement("bb-llm-input-array") -export class LLMInputArray extends LitElement { - @property() - values: LLMContent[] | null = null; - - @property() - description: string | null = null; - - @property() - showEntrySelector = true; - - @property({ reflect: true }) - clamped = true; - - @property({ reflect: true }) - inlineControls = false; - - @property() - minItems = 0; - - @property() - allow: AllowedLLMContentTypes = { - audioFile: true, - audioMicrophone: true, - videoFile: true, - videoWebcam: true, - imageFile: true, - imageWebcam: true, - imageDrawable: true, - textFile: true, - textInline: true, - }; - - @property({ reflect: true }) - selected = 0; - - #resizeObserver: ResizeObserver | null = null; - #activeLLMContentRef: Ref = createRef(); - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: block; - } - - header { - font: 400 var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - margin: 0 0 var(--bb-grid-size-2) 0; - } - - #controls { - display: flex; - flex-direction: row; - align-items: center; - margin: var(--bb-grid-size-4) 0 var(--bb-grid-size-2) 0; - min-height: var(--bb-grid-size-7); - } - - #controls h1 { - font: 400 var(--bb-label-large) / var(--bb-label-line-height-large) - var(--bb-font-family); - margin-right: var(--bb-grid-size); - } - - #controls button { - cursor: pointer; - width: var(--bb-grid-size-7); - height: var(--bb-grid-size-7); - margin-right: var(--bb-grid-size); - border-radius: 50%; - border: 1px solid var(--bb-neutral-300); - font-size: 0; - background: var(--bb-neutral-0) var(--bb-icon-human) center center / 20px - 20px no-repeat; - } - - #controls button.model { - background: var(--bb-neutral-0) var(--bb-icon-model) center center / 20px - 20px no-repeat; - } - - #controls button.user { - background: var(--bb-neutral-0) var(--bb-icon-human) center center / 20px - 20px no-repeat; - } - - #controls button[disabled] { - cursor: auto; - background-color: var(--bb-ui-100); - } - - bb-llm-input { - display: none; - } - - bb-llm-input.visible { - display: block; - } - `; - - #containerRef: Ref = createRef(); - - processAllOpenParts() { - if (!this.#containerRef.value) { - return; - } - - const inputs = - this.#containerRef.value.querySelectorAll("bb-llm-input"); - return [...inputs].map((input) => input.processAllOpenParts()); - } - - hasMinItems(): boolean { - if (!this.#containerRef.value) { - return false; - } - - const inputs = - this.#containerRef.value.querySelectorAll("bb-llm-input"); - return [...inputs].every((input) => input.hasMinItems()); - } - - get value() { - return this.values; - } - - protected willUpdate( - changedProperties: - | PropertyValueMap<{ values: LLMContent[] | null }> - | Map - ): void { - if (!changedProperties.has("values")) { - return; - } - - if (!this.values) { - return; - } - - if (this.values.length === 0) { - this.values.push({ role: "user", parts: [] }); - } - - this.selected = this.values.length - 1; - } - - protected updated(): void { - if (this.#resizeObserver) { - this.#resizeObserver.disconnect(); - } - - if (!this.#activeLLMContentRef.value) { - return; - } - - this.#resizeObserver = new ResizeObserver(() => { - if (!this.#containerRef.value) { - return; - } - - if (!this.#activeLLMContentRef.value) { - return; - } - - const containerHeight = - this.#activeLLMContentRef.value.getContainerHeight(); - const llmContents = this.#containerRef.value.querySelectorAll( - "bb-llm-input:not(.visible)" - ); - for (const llmContent of llmContents) { - llmContent.setContainerHeight(containerHeight); - } - }); - - this.#resizeObserver.observe(this.#activeLLMContentRef.value); - } - - render() { - return html`
    - ${this.description ? html`${this.description}` : nothing} -
    - - ${this.showEntrySelector - ? html`
    -

    Role

    - ${this.values && this.values.length - ? map(this.values, (item, idx) => { - const roleClass = (item.role || "user") - .toLocaleLowerCase() - .replaceAll(/\s/gim, "-"); - return html``; - }) - : html`No items specified`} -
    ` - : nothing} - -
    - ${this.values - ? map(this.values, (value, idx) => { - if (value.role === "$metadata") return nothing; - return html` { - if (!this.values) { - return; - } - - if (!(evt.target instanceof LLMInput)) { - return; - } - - if (!evt.target.value) { - return; - } - - this.values[idx] = evt.target.value; - }} - ${idx === this.selected - ? ref(this.#activeLLMContentRef) - : nothing} - .value=${value} - .minItems=${this.minItems} - .clamped=${this.clamped} - .inlineControls=${this.inlineControls} - .allow=${this.allow} - >`; - }) - : html`No items specified`} -
    `; - } -} diff --git a/packages/shared-ui/src/elements/input/llm-input/llm-input.ts b/packages/shared-ui/src/elements/input/llm-input/llm-input.ts deleted file mode 100644 index 0f7952aed90..00000000000 --- a/packages/shared-ui/src/elements/input/llm-input/llm-input.ts +++ /dev/null @@ -1,1181 +0,0 @@ -/** - * @license - * Copyright 2024 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -import { LitElement, html, css, HTMLTemplateResult, nothing } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import { AllowedLLMContentTypes } from "../../../types/types.js"; -import { map } from "lit/directives/map.js"; -import { classMap } from "lit/directives/class-map.js"; -import { Ref, createRef, ref } from "lit/directives/ref.js"; -import { until } from "lit/directives/until.js"; -import { cache } from "lit/directives/cache.js"; -import type { AudioInput } from "../audio/audio.js"; -import type { DrawableInput } from "../drawable/drawable.js"; -import type { WebcamInput } from "../webcam/webcam.js"; -import { - InlineDataCapabilityPart, - isFunctionCallCapabilityPart, - isFunctionResponseCapabilityPart, - isInlineData, - isStoredData, - isTextCapabilityPart, - LLMContent, - StoredDataCapabilityPart, - toInlineDataPart, -} from "@google-labs/breadboard"; -import { asBase64 } from "../../../utils/as-base-64.js"; -import { styleMap } from "lit/directives/style-map.js"; - -const inlineDataTemplate = { inlineData: { data: "", mimeType: "" } }; - -const OVERFLOW_MENU_HEIGHT = 224; -const OVERFLOW_MENU_WIDTH = 220; -const OVERFLOW_MENU_PADDING = 20; - -type MultiModalInput = AudioInput | DrawableInput | WebcamInput; - -@customElement("bb-llm-input") -export class LLMInput extends LitElement { - @property() - value: LLMContent | null = null; - - @property() - description: string | null = null; - - @property({ reflect: true }) - clamped = true; - - @property({ reflect: true }) - inlineControls = false; - - @property() - minItems = 0; - - @property() - allow: AllowedLLMContentTypes = { - audioFile: true, - audioMicrophone: true, - videoFile: true, - videoWebcam: true, - imageFile: true, - imageWebcam: true, - imageDrawable: true, - textFile: true, - textInline: true, - }; - - @state() - showInlineControls: { x: number; y: number } | null = null; - - #forceRenderCount = 0; - #focusLastPart = false; - #triggerSelectionFlow = false; - #lastPartRef: Ref = createRef(); - #lastInputRef: Ref = createRef(); - #containerRef: Ref = createRef(); - #controlsRef: Ref = createRef(); - - #partDataURLs = new Map(); - #onWindowPointerDownBound = this.#onWindowPointerDown.bind(this); - #onWindowKeyUpBound = this.#onWindowKeyUp.bind(this); - - static styles = css` - * { - box-sizing: border-box; - } - - :host { - display: block; - font: normal var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family); - position: relative; - } - - header { - display: block; - position: relative; - } - - header::empty { - background: red; - height: 20px; - } - - #description { - margin-bottom: var(--bb-grid-size-2); - } - - #controls { - color: var(--bb-neutral-700); - display: flex; - align-items: center; - padding: var(--bb-grid-size); - background: var(--bb-neutral-100); - border-radius: var(--bb-grid-size-2) var(--bb-grid-size-2) 0 0; - width: fit-content; - height: var(--bb-grid-size-7); - } - - #controls > #insert { - margin: 0 var(--bb-grid-size-2); - } - - #controls button { - width: 20px; - height: 20px; - opacity: 0.5; - margin: 0 var(--bb-grid-size); - border: none; - border-radius: 0; - font-size: 0; - cursor: pointer; - background: transparent var(--bb-icon-add-text) center center / 20px 20px - no-repeat; - } - - #controls #add-text { - background-image: var(--bb-icon-add-text); - } - - #controls #add-image-webcam { - background-image: var(--bb-icon-add-image-webcam); - } - - #controls #add-image-drawable { - background-image: var(--bb-icon-add-drawable); - } - - #controls #add-video-webcam { - background-image: var(--bb-icon-add-video); - } - - #controls #add-audio-microphone { - background-image: var(--bb-icon-add-audio); - } - - #controls #add-file { - background-image: var(--bb-icon-add-file); - } - - #controls #add-text:hover, - #controls #add-image-webcam:hover, - #controls #add-image-drawable:hover, - #controls #add-video-webcam:hover, - #controls #add-audio-microphone:hover, - #controls #add-file:hover, - #controls #add-text:focus, - #controls #add-image-webcam:focus, - #controls #add-image-drawable:focus, - #controls #add-video-webcam:focus, - #controls #add-audio-microphone:focus, - #controls #add-file:focus { - opacity: 1; - } - - :host([inlinecontrols="true"]) #controls-container { - position: fixed; - background: var(--bb-neutral-0); - border: 1px solid var(--bb-neutral-300); - border-radius: var(--bb-grid-size-2); - box-shadow: - 0px 4px 8px 3px rgba(0, 0, 0, 0.05), - 0px 1px 3px rgba(0, 0, 0, 0.1); - z-index: 1; - } - - :host([inlinecontrols="true"]) #controls { - display: grid; - grid-template-rows: var(--bb-grid-size-11); - background: none; - height: 224px; - padding: 0; - } - - :host([inlinecontrols="true"]) #insert { - display: none; - } - - :host([inlinecontrols="true"]) #controls button { - display: flex; - align-items: center; - background: none; - margin: 0; - padding: var(--bb-grid-size-3) var(--bb-grid-size-3) var(--bb-grid-size-3) - var(--bb-grid-size-8); - border: none; - border-bottom: 1px solid var(--bb-neutral-300); - text-align: left; - cursor: pointer; - font: 400 var(--bb-title-small) / var(--bb-title-line-height-small) - var(--bb-font-family); - width: auto; - height: auto; - background-position: var(--bb-grid-size-2) center; - background-repeat: no-repeat; - opacity: 1; - } - - :host([inlinecontrols="true"]) #controls button:hover, - :host([inlinecontrols="true"]) #controls button:focus { - background-color: var(--bb-neutral-50); - } - - :host([inlinecontrols="true"]) #controls button:last-of-type { - border-bottom: none; - } - - #toggle-controls { - position: absolute; - width: 20px; - height: 20px; - background: var(--bb-ui-500) var(--bb-icon-add-inverted) center center / - 20px 20px no-repeat; - border-radius: 50%; - font-size: 0; - border: none; - bottom: calc(var(--bb-grid-size-9) * -1); - right: var(--bb-grid-size-3); - cursor: pointer; - opacity: 0.75; - transition: opacity 0.3s cubic-bezier(0, 0, 0.3, 1); - } - - header.with-description #toggle-controls { - bottom: calc(var(--bb-grid-size-11) * -1); - } - - #toggle-controls:hover, - #toggle-controls:focus { - opacity: 1; - transition-duration: 0.1s; - } - - #container { - border: 1px solid var(--bb-neutral-300); - border-radius: 0 0 var(--bb-grid-size) var(--bb-grid-size); - padding: var(--bb-grid-size-3) 0 var(--bb-grid-size) 0; - background: #fff; - } - - :host([clamped="true"]) #container { - resize: vertical; - overflow: auto; - height: 160px; - min-height: var(--bb-grid-size-6); - } - - :host([inlinecontrols="true"]) #container { - padding-right: var(--bb-grid-size-7); - border-radius: var(--bb-grid-size); - } - - .content { - display: block; - margin-bottom: var(--bb-grid-size-2); - } - - .part { - position: relative; - margin: 0 var(--bb-grid-size-3); - } - - .part-controls { - display: none; - position: absolute; - top: calc(var(--bb-grid-size-4) * -1 - 2px); - right: calc(var(--bb-grid-size-2) * -1); - height: var(--bb-grid-size-7); - padding: var(--bb-grid-size) var(--bb-grid-size-2); - border-radius: var(--bb-grid-size-8); - border: 1px solid var(--bb-neutral-300); - background: #fff; - } - - .part:hover .part-controls { - display: flex; - } - - .part-controls .add-part-after, - .part-controls .move-part-up, - .part-controls .move-part-down, - .part-controls .delete-part { - width: 20px; - height: 20px; - opacity: 0.5; - margin-right: var(--bb-grid-size); - border: none; - border-radius: 0; - font-size: 0; - cursor: pointer; - } - - .part-controls .add-part-after { - background: #fff var(--bb-icon-add) center center / 16px 16px no-repeat; - } - - .part-controls .move-part-up { - background: #fff var(--bb-icon-move-up) center center / 16px 16px - no-repeat; - } - - .part-controls .move-part-down { - background: #fff var(--bb-icon-move-down) center center / 16px 16px - no-repeat; - } - - .part-controls .delete-part { - background: #fff var(--bb-icon-delete) center center / 16px 16px no-repeat; - margin-right: 0; - } - - .part-controls .add-part-after:hover, - .part-controls .move-part-up:hover, - .part-controls .move-part-down:hover, - .part-controls .delete-part:hover, - .part-controls .add-part-after:focus, - .part-controls .move-part-up:focus, - .part-controls .move-part-down:focus, - .part-controls .delete-part:focus { - opacity: 1; - } - - .part-controls .move-part-up[disabled], - .part-controls .move-part-down[disabled] { - opacity: 0.3; - cursor: auto; - } - - .value { - display: flex; - flex-direction: column; - position: relative; - padding: var(--bb-grid-size) var(--bb-grid-size) var(--bb-grid-size) - var(--bb-grid-size-3); - font: normal var(--bb-body-medium) / var(--bb-body-line-height-medium) - var(--bb-font-family); - color: var(--bb-neutral-900); - margin-left: 0; - } - - .value::before { - content: ""; - position: absolute; - top: 0; - left: 0; - height: 100%; - border-radius: var(--bb-grid-size-3); - background: var(--bb-ui-100); - width: 3px; - } - - .part:hover { - background: var(--bb-neutral-50); - } - - .part:hover .value::before { - background: var(--bb-ui-300); - } - - .part:focus-within { - background: var(--bb-ui-50); - } - - .value textarea { - background: transparent; - font: normal var(--bb-body-medium) / var(--bb-body-line-height-medium) - var(--bb-font-family); - color: var(--bb-neutral-900); - white-space: pre-line; - resize: none; - field-sizing: content; - margin: 0; - padding: 0; - border: none; - width: 100%; - outline: none; - } - - .value * { - margin: var(--bb-grid-size) 0; - background: transparent; - } - - .value h1 { - font-size: var(--bb-title-large); - margin: calc(var(--bb-grid-size) * 4) 0 calc(var(--bb-grid-size) * 1) 0; - } - - .value h2 { - font-size: var(--bb-title-medium); - margin: calc(var(--bb-grid-size) * 4) 0 calc(var(--bb-grid-size) * 1) 0; - } - - .value h3, - .value h4, - .value h5 { - font-size: var(--bb-title-small); - margin: 0 0 calc(var(--bb-grid-size) * 2) 0; - } - - .value p { - font-size: var(--bb-body-medium); - margin: 0 0 calc(var(--bb-grid-size) * 2) 0; - } - - .value h1:first-of-type, - .value h2:first-of-type, - .value h3:first-of-type, - .value h4:first-of-type, - .value h5:first-of-type { - margin-top: 0; - } - - .value p:last-of-type { - margin-bottom: 0; - } - - .value img, - .value video, - .value audio { - width: 100%; - max-width: 320px; - } - - .value img, - .value video { - outline: 1px solid var(--bb-neutral-300); - border-radius: var(--bb-grid-size); - } - - .value .plain-text { - white-space: pre; - font: normal var(--bb-body-small) / var(--bb-body-line-height-small) - var(--bb-font-family-mono); - color: var(--bb-neutral-600); - } - - .value bb-webcam-input { - --bb-border-radius: var(--bb-grid-size); - --bb-box-shadow: none; - --bb-outline: var(--bb-neutral-300); - width: 100%; - max-width: 320px; - } - - .value bb-drawable-input { - --bb-border-radius: var(--bb-grid-size); - --bb-box-shadow: none; - --bb-outline: var(--bb-neutral-300); - width: 100%; - max-width: 320px; - } - - #no-parts { - position: relative; - margin: 0 var(--bb-grid-size-3); - - font: normal var(--bb-body-medium) / var(--bb-body-line-height-medium) - var(--bb-font-family); - } - - #no-parts .add-text { - background: var(--bb-continue-color); - color: var(--bb-ui-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4); - margin: 0; - font: normal var(--bb-body-medium) / var(--bb-body-line-height-medium) - var(--bb-font-family); - } - - :host([inlinecontrols="true"]) #no-parts { - margin-bottom: var(--bb-grid-size-2); - min-height: var(--bb-grid-size-7); - } - - .confirm { - background: var(--bb-continue-color) var(--bb-icon-confirm-blue) 8px 4px / - 16px 16px no-repeat; - color: var(--bb-ui-700); - border-radius: var(--bb-grid-size-5); - border: none; - height: var(--bb-grid-size-6); - padding: 0 var(--bb-grid-size-4) 0 var(--bb-grid-size-7); - margin: var(--bb-grid-size-2) 0 var(--bb-grid-size) 0; - } - `; - - #onWindowPointerDown() { - if (!this.showInlineControls) { - return; - } - - this.showInlineControls = null; - } - - #onWindowKeyUp(evt: KeyboardEvent) { - if (!this.showInlineControls) { - return; - } - - if (evt.key === "Enter") { - return; - } - - if (!this.shadowRoot || !this.#controlsRef.value) { - return; - } - - // If there's no active element in this shadow root or if it has moved to - // outside the controls, hide the overflow menu. - if ( - !this.shadowRoot.activeElement || - this.shadowRoot.activeElement.parentElement !== this.#controlsRef.value - ) { - this.showInlineControls = null; - return; - } - } - - connectedCallback(): void { - super.connectedCallback(); - - this.#clearPartDataURLs(); - if (!this.inlineControls) { - return; - } - - window.addEventListener("click", this.#onWindowPointerDownBound); - window.addEventListener("keyup", this.#onWindowKeyUpBound); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - - window.removeEventListener("click", this.#onWindowPointerDownBound); - window.removeEventListener("keyup", this.#onWindowKeyUpBound); - } - - getContainerHeight(): number { - if (!this.#containerRef.value) { - return 0; - } - - return this.#containerRef.value.getBoundingClientRect().height || 0; - } - - setContainerHeight(height: number) { - if (!this.#containerRef.value) { - return; - } - - this.#containerRef.value.style.height = `${height}px`; - } - - hasMinItems(): boolean { - if (!this.value) { - return false; - } - - return this.value.parts.length >= this.minItems; - } - - #clearPartDataURLs() { - for (const url of this.#partDataURLs.values()) { - URL.revokeObjectURL(url); - } - - this.#partDataURLs.clear(); - } - - #emitUpdate() { - this.dispatchEvent( - new InputEvent("input", { - bubbles: true, - composed: true, - cancelable: true, - }) - ); - } - - #addTextPart() { - if (!this.value) { - this.value = { role: "user", parts: [] }; - } - - this.showInlineControls = null; - this.value.parts.push({ text: "" }); - this.#focusLastPart = true; - - this.#forceReRender(); - this.requestUpdate(); - } - - #addPart(mimeType: string, triggerSelectionFlow = true) { - if (!this.value) { - this.value = { role: "user", parts: [] }; - } - - this.showInlineControls = null; - this.value.parts.push({ inlineData: { data: "", mimeType } }); - this.#focusLastPart = true; - this.#triggerSelectionFlow = triggerSelectionFlow; - this.requestUpdate(); - } - - protected updated(): void { - const focusLastPart = this.#focusLastPart; - const triggerSelectionFlow = this.#triggerSelectionFlow; - this.#focusLastPart = false; - this.#triggerSelectionFlow = false; - - if (focusLastPart && this.#lastPartRef.value) { - this.#lastPartRef.value.focus(); - } - - if (triggerSelectionFlow) { - requestAnimationFrame(() => { - if (!this.#lastInputRef.value) { - return; - } - - this.#lastInputRef.value.click(); - }); - } - } - - processAllOpenParts() { - if (!this.value) { - return; - } - - this.value.parts.map((part, idx) => { - if (!isInlineData(part)) { - return; - } - - switch (part.inlineData.mimeType) { - case "audio-microphone": - case "image-webcam": - case "image-drawable": { - return this.#processInputPart(idx); - } - } - }); - } - - async #processFilePart(evt: InputEvent, partIdx: number) { - if (!(evt.target instanceof HTMLInputElement)) { - return; - } - - const { files } = evt.target; - if (!files || files.length === 0) { - return; - } - - if (!this.value) { - this.value = { role: "user", parts: [] }; - } - - if (!this.value.parts[partIdx]) { - this.value.parts[partIdx] = structuredClone(inlineDataTemplate); - } - let part = this.value.parts[partIdx]; - - if (!isInlineData(part)) { - part = structuredClone(inlineDataTemplate); - } - - part.inlineData.data = await asBase64(files[0]); - part.inlineData.mimeType = files[0].type; - this.#partDataURLs.delete(partIdx); - - this.#emitUpdate(); - this.requestUpdate(); - } - - #processInputPart(partIdx: number) { - if (!this.value) { - this.value = { role: "user", parts: [] }; - } - - if (!this.value.parts[partIdx]) { - this.value.parts[partIdx] = structuredClone(inlineDataTemplate); - } - - let part = this.value.parts[partIdx]; - if (!isInlineData(part)) { - part = structuredClone(inlineDataTemplate); - } - - switch (part.inlineData.mimeType) { - case "audio-microphone": - case "image-webcam": - case "image-drawable": { - const inputEl = - this.#containerRef.value?.querySelector( - `#part-${partIdx}` - ); - if (!inputEl) { - break; - } - - const content = inputEl.value as LLMContent; - if (!content.parts.length || !isInlineData(content.parts[0])) { - break; - } - - const contentPart = content.parts[0]; - part.inlineData = contentPart.inlineData; - this.#partDataURLs.delete(partIdx); - break; - } - } - - this.#emitUpdate(); - this.requestUpdate(); - } - - #move(idx: number, distance: number) { - if (!this.value) { - return; - } - - if (idx + distance < 0 || idx + distance >= this.value.parts.length) { - return; - } - - const tempPart = this.value.parts[idx + distance]; - this.value.parts[idx + distance] = this.value.parts[idx]; - this.value.parts[idx] = tempPart; - - const tempUrlA = this.#partDataURLs.get(idx); - const tempUrlB = this.#partDataURLs.get(idx + distance); - if (tempUrlA && tempUrlB) { - this.#partDataURLs.set(idx, tempUrlB); - this.#partDataURLs.set(idx + distance, tempUrlA); - } - - this.#forceReRender(); - } - - #addPartAfter(idx: number) { - if (!this.value) { - return; - } - - this.value.parts.splice(idx + 1, 0, { text: "" }); - this.#forceReRender(); - } - - #movePartUp(idx: number) { - this.#move(idx, -1); - } - - #movePartDown(idx: number) { - this.#move(idx, 1); - } - - #deletePart(idx: number) { - if (!this.value) { - return; - } - - this.value.parts.splice(idx, 1); - if (this.value.parts.length === 0) { - this.value = null; - } - this.#forceReRender(); - } - - #forceReRender() { - this.#emitUpdate(); - this.#forceRenderCount++; - this.requestUpdate(); - } - - #createAcceptList() { - const accept = []; - if (this.allow.audioFile) { - accept.push("audio/*"); - } - - if (this.allow.videoFile) { - accept.push("video/*"); - } - - if (this.allow.imageFile) { - accept.push("image/*"); - } - - if (this.allow.textFile) { - accept.push("text/plain"); - } - - if (accept.length === 0) { - console.warn("No file types are allowed - defaulting to text"); - accept.push("text/plain"); - } - - return accept.join(","); - } - - async #getPartDataAsHTML( - idx: number, - part: InlineDataCapabilityPart | StoredDataCapabilityPart, - isLastPart = false - ) { - let mimeType; - let getData: () => Promise; - let url; - if (isInlineData(part)) { - url = this.#partDataURLs.get(idx); - mimeType = part.inlineData.mimeType; - getData = async () => atob(part.inlineData.data); - if (!url && part.inlineData.data !== "") { - const dataURL = `data:${part.inlineData.mimeType};base64,${part.inlineData.data}`; - const response = await fetch(dataURL); - url = URL.createObjectURL(await response.blob()); - this.#partDataURLs.set(idx, url); - } - } else { - url = part.storedData.handle; - mimeType = part.storedData.mimeType; - getData = async () => { - const response = await toInlineDataPart(part); - if (!response) { - return "Unable to retrieve data"; - } - return atob(response.inlineData.data); - }; - } - - switch (mimeType) { - case "image/png": - case "image/jpg": - case "image/jpeg": - case "image/heic": - case "image/heif": - case "image/webp": { - return cache(html`LLM Image`); - } - - case "audio/wav": - case "audio/x-m4a": - case "audio/m4a": - case "audio/webm": - case "audio/mp3": - case "audio/mpeg": { - return cache(html`